xref: /openbmc/qemu/qga/commands-posix.c (revision 77a8257e)
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 <unistd.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <dirent.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <inttypes.h>
26 #include "qga/guest-agent-core.h"
27 #include "qga-qmp-commands.h"
28 #include "qapi/qmp/qerror.h"
29 #include "qemu/queue.h"
30 #include "qemu/host-utils.h"
31 
32 #ifndef CONFIG_HAS_ENVIRON
33 #ifdef __APPLE__
34 #include <crt_externs.h>
35 #define environ (*_NSGetEnviron())
36 #else
37 extern char **environ;
38 #endif
39 #endif
40 
41 #if defined(__linux__)
42 #include <mntent.h>
43 #include <linux/fs.h>
44 #include <ifaddrs.h>
45 #include <arpa/inet.h>
46 #include <sys/socket.h>
47 #include <net/if.h>
48 
49 #ifdef FIFREEZE
50 #define CONFIG_FSFREEZE
51 #endif
52 #ifdef FITRIM
53 #define CONFIG_FSTRIM
54 #endif
55 #endif
56 
57 static void ga_wait_child(pid_t pid, int *status, Error **errp)
58 {
59     pid_t rpid;
60 
61     *status = 0;
62 
63     do {
64         rpid = waitpid(pid, status, 0);
65     } while (rpid == -1 && errno == EINTR);
66 
67     if (rpid == -1) {
68         error_setg_errno(errp, errno, "failed to wait for child (pid: %d)",
69                          pid);
70         return;
71     }
72 
73     g_assert(rpid == pid);
74 }
75 
76 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp)
77 {
78     const char *shutdown_flag;
79     Error *local_err = NULL;
80     pid_t pid;
81     int status;
82 
83     slog("guest-shutdown called, mode: %s", mode);
84     if (!has_mode || strcmp(mode, "powerdown") == 0) {
85         shutdown_flag = "-P";
86     } else if (strcmp(mode, "halt") == 0) {
87         shutdown_flag = "-H";
88     } else if (strcmp(mode, "reboot") == 0) {
89         shutdown_flag = "-r";
90     } else {
91         error_setg(errp,
92                    "mode is invalid (valid values are: halt|powerdown|reboot");
93         return;
94     }
95 
96     pid = fork();
97     if (pid == 0) {
98         /* child, start the shutdown */
99         setsid();
100         reopen_fd_to_null(0);
101         reopen_fd_to_null(1);
102         reopen_fd_to_null(2);
103 
104         execle("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0",
105                "hypervisor initiated shutdown", (char*)NULL, environ);
106         _exit(EXIT_FAILURE);
107     } else if (pid < 0) {
108         error_setg_errno(errp, errno, "failed to create child process");
109         return;
110     }
111 
112     ga_wait_child(pid, &status, &local_err);
113     if (local_err) {
114         error_propagate(errp, local_err);
115         return;
116     }
117 
118     if (!WIFEXITED(status)) {
119         error_setg(errp, "child process has terminated abnormally");
120         return;
121     }
122 
123     if (WEXITSTATUS(status)) {
124         error_setg(errp, "child process has failed to shutdown");
125         return;
126     }
127 
128     /* succeeded */
129 }
130 
131 int64_t qmp_guest_get_time(Error **errp)
132 {
133    int ret;
134    qemu_timeval tq;
135    int64_t time_ns;
136 
137    ret = qemu_gettimeofday(&tq);
138    if (ret < 0) {
139        error_setg_errno(errp, errno, "Failed to get time");
140        return -1;
141    }
142 
143    time_ns = tq.tv_sec * 1000000000LL + tq.tv_usec * 1000;
144    return time_ns;
145 }
146 
147 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
148 {
149     int ret;
150     int status;
151     pid_t pid;
152     Error *local_err = NULL;
153     struct timeval tv;
154 
155     /* If user has passed a time, validate and set it. */
156     if (has_time) {
157         /* year-2038 will overflow in case time_t is 32bit */
158         if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
159             error_setg(errp, "Time %" PRId64 " is too large", time_ns);
160             return;
161         }
162 
163         tv.tv_sec = time_ns / 1000000000;
164         tv.tv_usec = (time_ns % 1000000000) / 1000;
165 
166         ret = settimeofday(&tv, NULL);
167         if (ret < 0) {
168             error_setg_errno(errp, errno, "Failed to set time to guest");
169             return;
170         }
171     }
172 
173     /* Now, if user has passed a time to set and the system time is set, we
174      * just need to synchronize the hardware clock. However, if no time was
175      * passed, user is requesting the opposite: set the system time from the
176      * hardware clock (RTC). */
177     pid = fork();
178     if (pid == 0) {
179         setsid();
180         reopen_fd_to_null(0);
181         reopen_fd_to_null(1);
182         reopen_fd_to_null(2);
183 
184         /* Use '/sbin/hwclock -w' to set RTC from the system time,
185          * or '/sbin/hwclock -s' to set the system time from RTC. */
186         execle("/sbin/hwclock", "hwclock", has_time ? "-w" : "-s",
187                NULL, environ);
188         _exit(EXIT_FAILURE);
189     } else if (pid < 0) {
190         error_setg_errno(errp, errno, "failed to create child process");
191         return;
192     }
193 
194     ga_wait_child(pid, &status, &local_err);
195     if (local_err) {
196         error_propagate(errp, local_err);
197         return;
198     }
199 
200     if (!WIFEXITED(status)) {
201         error_setg(errp, "child process has terminated abnormally");
202         return;
203     }
204 
205     if (WEXITSTATUS(status)) {
206         error_setg(errp, "hwclock failed to set hardware clock to system time");
207         return;
208     }
209 }
210 
211 typedef struct GuestFileHandle {
212     uint64_t id;
213     FILE *fh;
214     QTAILQ_ENTRY(GuestFileHandle) next;
215 } GuestFileHandle;
216 
217 static struct {
218     QTAILQ_HEAD(, GuestFileHandle) filehandles;
219 } guest_file_state;
220 
221 static int64_t guest_file_handle_add(FILE *fh, Error **errp)
222 {
223     GuestFileHandle *gfh;
224     int64_t handle;
225 
226     handle = ga_get_fd_handle(ga_state, errp);
227     if (handle < 0) {
228         return -1;
229     }
230 
231     gfh = g_malloc0(sizeof(GuestFileHandle));
232     gfh->id = handle;
233     gfh->fh = fh;
234     QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
235 
236     return handle;
237 }
238 
239 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp)
240 {
241     GuestFileHandle *gfh;
242 
243     QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
244     {
245         if (gfh->id == id) {
246             return gfh;
247         }
248     }
249 
250     error_setg(errp, "handle '%" PRId64 "' has not been found", id);
251     return NULL;
252 }
253 
254 typedef const char * const ccpc;
255 
256 #ifndef O_BINARY
257 #define O_BINARY 0
258 #endif
259 
260 /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */
261 static const struct {
262     ccpc *forms;
263     int oflag_base;
264 } guest_file_open_modes[] = {
265     { (ccpc[]){ "r",          NULL }, O_RDONLY                                 },
266     { (ccpc[]){ "rb",         NULL }, O_RDONLY                      | O_BINARY },
267     { (ccpc[]){ "w",          NULL }, O_WRONLY | O_CREAT | O_TRUNC             },
268     { (ccpc[]){ "wb",         NULL }, O_WRONLY | O_CREAT | O_TRUNC  | O_BINARY },
269     { (ccpc[]){ "a",          NULL }, O_WRONLY | O_CREAT | O_APPEND            },
270     { (ccpc[]){ "ab",         NULL }, O_WRONLY | O_CREAT | O_APPEND | O_BINARY },
271     { (ccpc[]){ "r+",         NULL }, O_RDWR                                   },
272     { (ccpc[]){ "rb+", "r+b", NULL }, O_RDWR                        | O_BINARY },
273     { (ccpc[]){ "w+",         NULL }, O_RDWR   | O_CREAT | O_TRUNC             },
274     { (ccpc[]){ "wb+", "w+b", NULL }, O_RDWR   | O_CREAT | O_TRUNC  | O_BINARY },
275     { (ccpc[]){ "a+",         NULL }, O_RDWR   | O_CREAT | O_APPEND            },
276     { (ccpc[]){ "ab+", "a+b", NULL }, O_RDWR   | O_CREAT | O_APPEND | O_BINARY }
277 };
278 
279 static int
280 find_open_flag(const char *mode_str, Error **errp)
281 {
282     unsigned mode;
283 
284     for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) {
285         ccpc *form;
286 
287         form = guest_file_open_modes[mode].forms;
288         while (*form != NULL && strcmp(*form, mode_str) != 0) {
289             ++form;
290         }
291         if (*form != NULL) {
292             break;
293         }
294     }
295 
296     if (mode == ARRAY_SIZE(guest_file_open_modes)) {
297         error_setg(errp, "invalid file open mode '%s'", mode_str);
298         return -1;
299     }
300     return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK;
301 }
302 
303 #define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \
304                                S_IRGRP | S_IWGRP | \
305                                S_IROTH | S_IWOTH)
306 
307 static FILE *
308 safe_open_or_create(const char *path, const char *mode, Error **errp)
309 {
310     Error *local_err = NULL;
311     int oflag;
312 
313     oflag = find_open_flag(mode, &local_err);
314     if (local_err == NULL) {
315         int fd;
316 
317         /* If the caller wants / allows creation of a new file, we implement it
318          * with a two step process: open() + (open() / fchmod()).
319          *
320          * First we insist on creating the file exclusively as a new file. If
321          * that succeeds, we're free to set any file-mode bits on it. (The
322          * motivation is that we want to set those file-mode bits independently
323          * of the current umask.)
324          *
325          * If the exclusive creation fails because the file already exists
326          * (EEXIST is not possible for any other reason), we just attempt to
327          * open the file, but in this case we won't be allowed to change the
328          * file-mode bits on the preexistent file.
329          *
330          * The pathname should never disappear between the two open()s in
331          * practice. If it happens, then someone very likely tried to race us.
332          * In this case just go ahead and report the ENOENT from the second
333          * open() to the caller.
334          *
335          * If the caller wants to open a preexistent file, then the first
336          * open() is decisive and its third argument is ignored, and the second
337          * open() and the fchmod() are never called.
338          */
339         fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0);
340         if (fd == -1 && errno == EEXIST) {
341             oflag &= ~(unsigned)O_CREAT;
342             fd = open(path, oflag);
343         }
344 
345         if (fd == -1) {
346             error_setg_errno(&local_err, errno, "failed to open file '%s' "
347                              "(mode: '%s')", path, mode);
348         } else {
349             qemu_set_cloexec(fd);
350 
351             if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) {
352                 error_setg_errno(&local_err, errno, "failed to set permission "
353                                  "0%03o on new file '%s' (mode: '%s')",
354                                  (unsigned)DEFAULT_NEW_FILE_MODE, path, mode);
355             } else {
356                 FILE *f;
357 
358                 f = fdopen(fd, mode);
359                 if (f == NULL) {
360                     error_setg_errno(&local_err, errno, "failed to associate "
361                                      "stdio stream with file descriptor %d, "
362                                      "file '%s' (mode: '%s')", fd, path, mode);
363                 } else {
364                     return f;
365                 }
366             }
367 
368             close(fd);
369             if (oflag & O_CREAT) {
370                 unlink(path);
371             }
372         }
373     }
374 
375     error_propagate(errp, local_err);
376     return NULL;
377 }
378 
379 static int guest_file_toggle_flags(int fd, int flags, bool set, Error **err)
380 {
381     int ret, old_flags;
382 
383     old_flags = fcntl(fd, F_GETFL);
384     if (old_flags == -1) {
385         error_set_errno(err, errno, QERR_QGA_COMMAND_FAILED,
386                         "failed to fetch filehandle flags");
387         return -1;
388     }
389 
390     ret = fcntl(fd, F_SETFL, set ? (old_flags | flags) : (old_flags & ~flags));
391     if (ret == -1) {
392         error_set_errno(err, errno, QERR_QGA_COMMAND_FAILED,
393                         "failed to set filehandle flags");
394         return -1;
395     }
396 
397     return ret;
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     if (guest_file_toggle_flags(fileno(fh), O_NONBLOCK, true, errp) < 0) {
421         fclose(fh);
422         return -1;
423     }
424 
425     handle = guest_file_handle_add(fh, errp);
426     if (handle < 0) {
427         fclose(fh);
428         return -1;
429     }
430 
431     slog("guest-file-open, handle: %" PRId64, handle);
432     return handle;
433 }
434 
435 void qmp_guest_file_close(int64_t handle, Error **errp)
436 {
437     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
438     int ret;
439 
440     slog("guest-file-close called, handle: %" PRId64, handle);
441     if (!gfh) {
442         return;
443     }
444 
445     ret = fclose(gfh->fh);
446     if (ret == EOF) {
447         error_setg_errno(errp, errno, "failed to close handle");
448         return;
449     }
450 
451     QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
452     g_free(gfh);
453 }
454 
455 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
456                                           int64_t count, Error **errp)
457 {
458     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
459     GuestFileRead *read_data = NULL;
460     guchar *buf;
461     FILE *fh;
462     size_t read_count;
463 
464     if (!gfh) {
465         return NULL;
466     }
467 
468     if (!has_count) {
469         count = QGA_READ_COUNT_DEFAULT;
470     } else if (count < 0) {
471         error_setg(errp, "value '%" PRId64 "' is invalid for argument count",
472                    count);
473         return NULL;
474     }
475 
476     fh = gfh->fh;
477     buf = g_malloc0(count+1);
478     read_count = fread(buf, 1, count, fh);
479     if (ferror(fh)) {
480         error_setg_errno(errp, errno, "failed to read file");
481         slog("guest-file-read failed, handle: %" PRId64, handle);
482     } else {
483         buf[read_count] = 0;
484         read_data = g_malloc0(sizeof(GuestFileRead));
485         read_data->count = read_count;
486         read_data->eof = feof(fh);
487         if (read_count) {
488             read_data->buf_b64 = g_base64_encode(buf, read_count);
489         }
490     }
491     g_free(buf);
492     clearerr(fh);
493 
494     return read_data;
495 }
496 
497 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
498                                      bool has_count, int64_t count,
499                                      Error **errp)
500 {
501     GuestFileWrite *write_data = NULL;
502     guchar *buf;
503     gsize buf_len;
504     int write_count;
505     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
506     FILE *fh;
507 
508     if (!gfh) {
509         return NULL;
510     }
511 
512     fh = gfh->fh;
513     buf = g_base64_decode(buf_b64, &buf_len);
514 
515     if (!has_count) {
516         count = buf_len;
517     } else if (count < 0 || count > buf_len) {
518         error_setg(errp, "value '%" PRId64 "' is invalid for argument count",
519                    count);
520         g_free(buf);
521         return NULL;
522     }
523 
524     write_count = fwrite(buf, 1, count, fh);
525     if (ferror(fh)) {
526         error_setg_errno(errp, errno, "failed to write to file");
527         slog("guest-file-write failed, handle: %" PRId64, handle);
528     } else {
529         write_data = g_malloc0(sizeof(GuestFileWrite));
530         write_data->count = write_count;
531         write_data->eof = feof(fh);
532     }
533     g_free(buf);
534     clearerr(fh);
535 
536     return write_data;
537 }
538 
539 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
540                                           int64_t whence, Error **errp)
541 {
542     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
543     GuestFileSeek *seek_data = NULL;
544     FILE *fh;
545     int ret;
546 
547     if (!gfh) {
548         return NULL;
549     }
550 
551     fh = gfh->fh;
552     ret = fseek(fh, offset, whence);
553     if (ret == -1) {
554         error_setg_errno(errp, errno, "failed to seek file");
555     } else {
556         seek_data = g_new0(GuestFileSeek, 1);
557         seek_data->position = ftell(fh);
558         seek_data->eof = feof(fh);
559     }
560     clearerr(fh);
561 
562     return seek_data;
563 }
564 
565 void qmp_guest_file_flush(int64_t handle, Error **errp)
566 {
567     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
568     FILE *fh;
569     int ret;
570 
571     if (!gfh) {
572         return;
573     }
574 
575     fh = gfh->fh;
576     ret = fflush(fh);
577     if (ret == EOF) {
578         error_setg_errno(errp, errno, "failed to flush file");
579     }
580 }
581 
582 static void guest_file_init(void)
583 {
584     QTAILQ_INIT(&guest_file_state.filehandles);
585 }
586 
587 /* linux-specific implementations. avoid this if at all possible. */
588 #if defined(__linux__)
589 
590 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
591 typedef struct FsMount {
592     char *dirname;
593     char *devtype;
594     unsigned int devmajor, devminor;
595     QTAILQ_ENTRY(FsMount) next;
596 } FsMount;
597 
598 typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList;
599 
600 static void free_fs_mount_list(FsMountList *mounts)
601 {
602      FsMount *mount, *temp;
603 
604      if (!mounts) {
605          return;
606      }
607 
608      QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
609          QTAILQ_REMOVE(mounts, mount, next);
610          g_free(mount->dirname);
611          g_free(mount->devtype);
612          g_free(mount);
613      }
614 }
615 
616 static int dev_major_minor(const char *devpath,
617                            unsigned int *devmajor, unsigned int *devminor)
618 {
619     struct stat st;
620 
621     *devmajor = 0;
622     *devminor = 0;
623 
624     if (stat(devpath, &st) < 0) {
625         slog("failed to stat device file '%s': %s", devpath, strerror(errno));
626         return -1;
627     }
628     if (S_ISDIR(st.st_mode)) {
629         /* It is bind mount */
630         return -2;
631     }
632     if (S_ISBLK(st.st_mode)) {
633         *devmajor = major(st.st_rdev);
634         *devminor = minor(st.st_rdev);
635         return 0;
636     }
637     return -1;
638 }
639 
640 /*
641  * Walk the mount table and build a list of local file systems
642  */
643 static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp)
644 {
645     struct mntent *ment;
646     FsMount *mount;
647     char const *mtab = "/proc/self/mounts";
648     FILE *fp;
649     unsigned int devmajor, devminor;
650 
651     fp = setmntent(mtab, "r");
652     if (!fp) {
653         error_setg(errp, "failed to open mtab file: '%s'", mtab);
654         return;
655     }
656 
657     while ((ment = getmntent(fp))) {
658         /*
659          * An entry which device name doesn't start with a '/' is
660          * either a dummy file system or a network file system.
661          * Add special handling for smbfs and cifs as is done by
662          * coreutils as well.
663          */
664         if ((ment->mnt_fsname[0] != '/') ||
665             (strcmp(ment->mnt_type, "smbfs") == 0) ||
666             (strcmp(ment->mnt_type, "cifs") == 0)) {
667             continue;
668         }
669         if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) {
670             /* Skip bind mounts */
671             continue;
672         }
673 
674         mount = g_malloc0(sizeof(FsMount));
675         mount->dirname = g_strdup(ment->mnt_dir);
676         mount->devtype = g_strdup(ment->mnt_type);
677         mount->devmajor = devmajor;
678         mount->devminor = devminor;
679 
680         QTAILQ_INSERT_TAIL(mounts, mount, next);
681     }
682 
683     endmntent(fp);
684 }
685 
686 static void decode_mntname(char *name, int len)
687 {
688     int i, j = 0;
689     for (i = 0; i <= len; i++) {
690         if (name[i] != '\\') {
691             name[j++] = name[i];
692         } else if (name[i + 1] == '\\') {
693             name[j++] = '\\';
694             i++;
695         } else if (name[i + 1] >= '0' && name[i + 1] <= '3' &&
696                    name[i + 2] >= '0' && name[i + 2] <= '7' &&
697                    name[i + 3] >= '0' && name[i + 3] <= '7') {
698             name[j++] = (name[i + 1] - '0') * 64 +
699                         (name[i + 2] - '0') * 8 +
700                         (name[i + 3] - '0');
701             i += 3;
702         } else {
703             name[j++] = name[i];
704         }
705     }
706 }
707 
708 static void build_fs_mount_list(FsMountList *mounts, Error **errp)
709 {
710     FsMount *mount;
711     char const *mountinfo = "/proc/self/mountinfo";
712     FILE *fp;
713     char *line = NULL, *dash;
714     size_t n;
715     char check;
716     unsigned int devmajor, devminor;
717     int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e;
718 
719     fp = fopen(mountinfo, "r");
720     if (!fp) {
721         build_fs_mount_list_from_mtab(mounts, errp);
722         return;
723     }
724 
725     while (getline(&line, &n, fp) != -1) {
726         ret = sscanf(line, "%*u %*u %u:%u %*s %n%*s%n%c",
727                      &devmajor, &devminor, &dir_s, &dir_e, &check);
728         if (ret < 3) {
729             continue;
730         }
731         dash = strstr(line + dir_e, " - ");
732         if (!dash) {
733             continue;
734         }
735         ret = sscanf(dash, " - %n%*s%n %n%*s%n%c",
736                      &type_s, &type_e, &dev_s, &dev_e, &check);
737         if (ret < 1) {
738             continue;
739         }
740         line[dir_e] = 0;
741         dash[type_e] = 0;
742         dash[dev_e] = 0;
743         decode_mntname(line + dir_s, dir_e - dir_s);
744         decode_mntname(dash + dev_s, dev_e - dev_s);
745         if (devmajor == 0) {
746             /* btrfs reports major number = 0 */
747             if (strcmp("btrfs", dash + type_s) != 0 ||
748                 dev_major_minor(dash + dev_s, &devmajor, &devminor) < 0) {
749                 continue;
750             }
751         }
752 
753         mount = g_malloc0(sizeof(FsMount));
754         mount->dirname = g_strdup(line + dir_s);
755         mount->devtype = g_strdup(dash + type_s);
756         mount->devmajor = devmajor;
757         mount->devminor = devminor;
758 
759         QTAILQ_INSERT_TAIL(mounts, mount, next);
760     }
761     free(line);
762 
763     fclose(fp);
764 }
765 #endif
766 
767 #if defined(CONFIG_FSFREEZE)
768 
769 static char *get_pci_driver(char const *syspath, int pathlen, Error **errp)
770 {
771     char *path;
772     char *dpath;
773     char *driver = NULL;
774     char buf[PATH_MAX];
775     ssize_t len;
776 
777     path = g_strndup(syspath, pathlen);
778     dpath = g_strdup_printf("%s/driver", path);
779     len = readlink(dpath, buf, sizeof(buf) - 1);
780     if (len != -1) {
781         buf[len] = 0;
782         driver = g_strdup(basename(buf));
783     }
784     g_free(dpath);
785     g_free(path);
786     return driver;
787 }
788 
789 static int compare_uint(const void *_a, const void *_b)
790 {
791     unsigned int a = *(unsigned int *)_a;
792     unsigned int b = *(unsigned int *)_b;
793 
794     return a < b ? -1 : a > b ? 1 : 0;
795 }
796 
797 /* Walk the specified sysfs and build a sorted list of host or ata numbers */
798 static int build_hosts(char const *syspath, char const *host, bool ata,
799                        unsigned int *hosts, int hosts_max, Error **errp)
800 {
801     char *path;
802     DIR *dir;
803     struct dirent *entry;
804     int i = 0;
805 
806     path = g_strndup(syspath, host - syspath);
807     dir = opendir(path);
808     if (!dir) {
809         error_setg_errno(errp, errno, "opendir(\"%s\")", path);
810         g_free(path);
811         return -1;
812     }
813 
814     while (i < hosts_max) {
815         entry = readdir(dir);
816         if (!entry) {
817             break;
818         }
819         if (ata && sscanf(entry->d_name, "ata%d", hosts + i) == 1) {
820             ++i;
821         } else if (!ata && sscanf(entry->d_name, "host%d", hosts + i) == 1) {
822             ++i;
823         }
824     }
825 
826     qsort(hosts, i, sizeof(hosts[0]), compare_uint);
827 
828     g_free(path);
829     closedir(dir);
830     return i;
831 }
832 
833 /* Store disk device info specified by @sysfs into @fs */
834 static void build_guest_fsinfo_for_real_device(char const *syspath,
835                                                GuestFilesystemInfo *fs,
836                                                Error **errp)
837 {
838     unsigned int pci[4], host, hosts[8], tgt[3];
839     int i, nhosts = 0, pcilen;
840     GuestDiskAddress *disk;
841     GuestPCIAddress *pciaddr;
842     GuestDiskAddressList *list = NULL;
843     bool has_ata = false, has_host = false, has_tgt = false;
844     char *p, *q, *driver = NULL;
845 
846     p = strstr(syspath, "/devices/pci");
847     if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n",
848                      pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) {
849         g_debug("only pci device is supported: sysfs path \"%s\"", syspath);
850         return;
851     }
852 
853     driver = get_pci_driver(syspath, (p + 12 + pcilen) - syspath, errp);
854     if (!driver) {
855         goto cleanup;
856     }
857 
858     p = strstr(syspath, "/target");
859     if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u",
860                     tgt, tgt + 1, tgt + 2) == 3) {
861         has_tgt = true;
862     }
863 
864     p = strstr(syspath, "/ata");
865     if (p) {
866         q = p + 4;
867         has_ata = true;
868     } else {
869         p = strstr(syspath, "/host");
870         q = p + 5;
871     }
872     if (p && sscanf(q, "%u", &host) == 1) {
873         has_host = true;
874         nhosts = build_hosts(syspath, p, has_ata, hosts,
875                              sizeof(hosts) / sizeof(hosts[0]), errp);
876         if (nhosts < 0) {
877             goto cleanup;
878         }
879     }
880 
881     pciaddr = g_malloc0(sizeof(*pciaddr));
882     pciaddr->domain = pci[0];
883     pciaddr->bus = pci[1];
884     pciaddr->slot = pci[2];
885     pciaddr->function = pci[3];
886 
887     disk = g_malloc0(sizeof(*disk));
888     disk->pci_controller = pciaddr;
889 
890     list = g_malloc0(sizeof(*list));
891     list->value = disk;
892 
893     if (strcmp(driver, "ata_piix") == 0) {
894         /* a host per ide bus, target*:0:<unit>:0 */
895         if (!has_host || !has_tgt) {
896             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
897             goto cleanup;
898         }
899         for (i = 0; i < nhosts; i++) {
900             if (host == hosts[i]) {
901                 disk->bus_type = GUEST_DISK_BUS_TYPE_IDE;
902                 disk->bus = i;
903                 disk->unit = tgt[1];
904                 break;
905             }
906         }
907         if (i >= nhosts) {
908             g_debug("no host for '%s' (driver '%s')", syspath, driver);
909             goto cleanup;
910         }
911     } else if (strcmp(driver, "sym53c8xx") == 0) {
912         /* scsi(LSI Logic): target*:0:<unit>:0 */
913         if (!has_tgt) {
914             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
915             goto cleanup;
916         }
917         disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
918         disk->unit = tgt[1];
919     } else if (strcmp(driver, "virtio-pci") == 0) {
920         if (has_tgt) {
921             /* virtio-scsi: target*:0:0:<unit> */
922             disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
923             disk->unit = tgt[2];
924         } else {
925             /* virtio-blk: 1 disk per 1 device */
926             disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO;
927         }
928     } else if (strcmp(driver, "ahci") == 0) {
929         /* ahci: 1 host per 1 unit */
930         if (!has_host || !has_tgt) {
931             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
932             goto cleanup;
933         }
934         for (i = 0; i < nhosts; i++) {
935             if (host == hosts[i]) {
936                 disk->unit = i;
937                 disk->bus_type = GUEST_DISK_BUS_TYPE_SATA;
938                 break;
939             }
940         }
941         if (i >= nhosts) {
942             g_debug("no host for '%s' (driver '%s')", syspath, driver);
943             goto cleanup;
944         }
945     } else {
946         g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath);
947         goto cleanup;
948     }
949 
950     list->next = fs->disk;
951     fs->disk = list;
952     g_free(driver);
953     return;
954 
955 cleanup:
956     if (list) {
957         qapi_free_GuestDiskAddressList(list);
958     }
959     g_free(driver);
960 }
961 
962 static void build_guest_fsinfo_for_device(char const *devpath,
963                                           GuestFilesystemInfo *fs,
964                                           Error **errp);
965 
966 /* Store a list of slave devices of virtual volume specified by @syspath into
967  * @fs */
968 static void build_guest_fsinfo_for_virtual_device(char const *syspath,
969                                                   GuestFilesystemInfo *fs,
970                                                   Error **errp)
971 {
972     DIR *dir;
973     char *dirpath;
974     struct dirent *entry;
975 
976     dirpath = g_strdup_printf("%s/slaves", syspath);
977     dir = opendir(dirpath);
978     if (!dir) {
979         error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath);
980         g_free(dirpath);
981         return;
982     }
983 
984     for (;;) {
985         errno = 0;
986         entry = readdir(dir);
987         if (entry == NULL) {
988             if (errno) {
989                 error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath);
990             }
991             break;
992         }
993 
994         if (entry->d_type == DT_LNK) {
995             char *path;
996 
997             g_debug(" slave device '%s'", entry->d_name);
998             path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name);
999             build_guest_fsinfo_for_device(path, fs, errp);
1000             g_free(path);
1001 
1002             if (*errp) {
1003                 break;
1004             }
1005         }
1006     }
1007 
1008     g_free(dirpath);
1009     closedir(dir);
1010 }
1011 
1012 /* Dispatch to functions for virtual/real device */
1013 static void build_guest_fsinfo_for_device(char const *devpath,
1014                                           GuestFilesystemInfo *fs,
1015                                           Error **errp)
1016 {
1017     char *syspath = realpath(devpath, NULL);
1018 
1019     if (!syspath) {
1020         error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
1021         return;
1022     }
1023 
1024     if (!fs->name) {
1025         fs->name = g_strdup(basename(syspath));
1026     }
1027 
1028     g_debug("  parse sysfs path '%s'", syspath);
1029 
1030     if (strstr(syspath, "/devices/virtual/block/")) {
1031         build_guest_fsinfo_for_virtual_device(syspath, fs, errp);
1032     } else {
1033         build_guest_fsinfo_for_real_device(syspath, fs, errp);
1034     }
1035 
1036     free(syspath);
1037 }
1038 
1039 /* Return a list of the disk device(s)' info which @mount lies on */
1040 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount,
1041                                                Error **errp)
1042 {
1043     GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs));
1044     char *devpath = g_strdup_printf("/sys/dev/block/%u:%u",
1045                                     mount->devmajor, mount->devminor);
1046 
1047     fs->mountpoint = g_strdup(mount->dirname);
1048     fs->type = g_strdup(mount->devtype);
1049     build_guest_fsinfo_for_device(devpath, fs, errp);
1050 
1051     g_free(devpath);
1052     return fs;
1053 }
1054 
1055 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
1056 {
1057     FsMountList mounts;
1058     struct FsMount *mount;
1059     GuestFilesystemInfoList *new, *ret = NULL;
1060     Error *local_err = NULL;
1061 
1062     QTAILQ_INIT(&mounts);
1063     build_fs_mount_list(&mounts, &local_err);
1064     if (local_err) {
1065         error_propagate(errp, local_err);
1066         return NULL;
1067     }
1068 
1069     QTAILQ_FOREACH(mount, &mounts, next) {
1070         g_debug("Building guest fsinfo for '%s'", mount->dirname);
1071 
1072         new = g_malloc0(sizeof(*ret));
1073         new->value = build_guest_fsinfo(mount, &local_err);
1074         new->next = ret;
1075         ret = new;
1076         if (local_err) {
1077             error_propagate(errp, local_err);
1078             qapi_free_GuestFilesystemInfoList(ret);
1079             ret = NULL;
1080             break;
1081         }
1082     }
1083 
1084     free_fs_mount_list(&mounts);
1085     return ret;
1086 }
1087 
1088 
1089 typedef enum {
1090     FSFREEZE_HOOK_THAW = 0,
1091     FSFREEZE_HOOK_FREEZE,
1092 } FsfreezeHookArg;
1093 
1094 static const char *fsfreeze_hook_arg_string[] = {
1095     "thaw",
1096     "freeze",
1097 };
1098 
1099 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp)
1100 {
1101     int status;
1102     pid_t pid;
1103     const char *hook;
1104     const char *arg_str = fsfreeze_hook_arg_string[arg];
1105     Error *local_err = NULL;
1106 
1107     hook = ga_fsfreeze_hook(ga_state);
1108     if (!hook) {
1109         return;
1110     }
1111     if (access(hook, X_OK) != 0) {
1112         error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook);
1113         return;
1114     }
1115 
1116     slog("executing fsfreeze hook with arg '%s'", arg_str);
1117     pid = fork();
1118     if (pid == 0) {
1119         setsid();
1120         reopen_fd_to_null(0);
1121         reopen_fd_to_null(1);
1122         reopen_fd_to_null(2);
1123 
1124         execle(hook, hook, arg_str, NULL, environ);
1125         _exit(EXIT_FAILURE);
1126     } else if (pid < 0) {
1127         error_setg_errno(errp, errno, "failed to create child process");
1128         return;
1129     }
1130 
1131     ga_wait_child(pid, &status, &local_err);
1132     if (local_err) {
1133         error_propagate(errp, local_err);
1134         return;
1135     }
1136 
1137     if (!WIFEXITED(status)) {
1138         error_setg(errp, "fsfreeze hook has terminated abnormally");
1139         return;
1140     }
1141 
1142     status = WEXITSTATUS(status);
1143     if (status) {
1144         error_setg(errp, "fsfreeze hook has failed with status %d", status);
1145         return;
1146     }
1147 }
1148 
1149 /*
1150  * Return status of freeze/thaw
1151  */
1152 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
1153 {
1154     if (ga_is_frozen(ga_state)) {
1155         return GUEST_FSFREEZE_STATUS_FROZEN;
1156     }
1157 
1158     return GUEST_FSFREEZE_STATUS_THAWED;
1159 }
1160 
1161 int64_t qmp_guest_fsfreeze_freeze(Error **errp)
1162 {
1163     return qmp_guest_fsfreeze_freeze_list(false, NULL, errp);
1164 }
1165 
1166 /*
1167  * Walk list of mounted file systems in the guest, and freeze the ones which
1168  * are real local file systems.
1169  */
1170 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
1171                                        strList *mountpoints,
1172                                        Error **errp)
1173 {
1174     int ret = 0, i = 0;
1175     strList *list;
1176     FsMountList mounts;
1177     struct FsMount *mount;
1178     Error *local_err = NULL;
1179     int fd;
1180 
1181     slog("guest-fsfreeze called");
1182 
1183     execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
1184     if (local_err) {
1185         error_propagate(errp, local_err);
1186         return -1;
1187     }
1188 
1189     QTAILQ_INIT(&mounts);
1190     build_fs_mount_list(&mounts, &local_err);
1191     if (local_err) {
1192         error_propagate(errp, local_err);
1193         return -1;
1194     }
1195 
1196     /* cannot risk guest agent blocking itself on a write in this state */
1197     ga_set_frozen(ga_state);
1198 
1199     QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) {
1200         /* To issue fsfreeze in the reverse order of mounts, check if the
1201          * mount is listed in the list here */
1202         if (has_mountpoints) {
1203             for (list = mountpoints; list; list = list->next) {
1204                 if (strcmp(list->value, mount->dirname) == 0) {
1205                     break;
1206                 }
1207             }
1208             if (!list) {
1209                 continue;
1210             }
1211         }
1212 
1213         fd = qemu_open(mount->dirname, O_RDONLY);
1214         if (fd == -1) {
1215             error_setg_errno(errp, errno, "failed to open %s", mount->dirname);
1216             goto error;
1217         }
1218 
1219         /* we try to cull filesytems we know won't work in advance, but other
1220          * filesytems may not implement fsfreeze for less obvious reasons.
1221          * these will report EOPNOTSUPP. we simply ignore these when tallying
1222          * the number of frozen filesystems.
1223          *
1224          * any other error means a failure to freeze a filesystem we
1225          * expect to be freezable, so return an error in those cases
1226          * and return system to thawed state.
1227          */
1228         ret = ioctl(fd, FIFREEZE);
1229         if (ret == -1) {
1230             if (errno != EOPNOTSUPP) {
1231                 error_setg_errno(errp, errno, "failed to freeze %s",
1232                                  mount->dirname);
1233                 close(fd);
1234                 goto error;
1235             }
1236         } else {
1237             i++;
1238         }
1239         close(fd);
1240     }
1241 
1242     free_fs_mount_list(&mounts);
1243     return i;
1244 
1245 error:
1246     free_fs_mount_list(&mounts);
1247     qmp_guest_fsfreeze_thaw(NULL);
1248     return 0;
1249 }
1250 
1251 /*
1252  * Walk list of frozen file systems in the guest, and thaw them.
1253  */
1254 int64_t qmp_guest_fsfreeze_thaw(Error **errp)
1255 {
1256     int ret;
1257     FsMountList mounts;
1258     FsMount *mount;
1259     int fd, i = 0, logged;
1260     Error *local_err = NULL;
1261 
1262     QTAILQ_INIT(&mounts);
1263     build_fs_mount_list(&mounts, &local_err);
1264     if (local_err) {
1265         error_propagate(errp, local_err);
1266         return 0;
1267     }
1268 
1269     QTAILQ_FOREACH(mount, &mounts, next) {
1270         logged = false;
1271         fd = qemu_open(mount->dirname, O_RDONLY);
1272         if (fd == -1) {
1273             continue;
1274         }
1275         /* we have no way of knowing whether a filesystem was actually unfrozen
1276          * as a result of a successful call to FITHAW, only that if an error
1277          * was returned the filesystem was *not* unfrozen by that particular
1278          * call.
1279          *
1280          * since multiple preceding FIFREEZEs require multiple calls to FITHAW
1281          * to unfreeze, continuing issuing FITHAW until an error is returned,
1282          * in which case either the filesystem is in an unfreezable state, or,
1283          * more likely, it was thawed previously (and remains so afterward).
1284          *
1285          * also, since the most recent successful call is the one that did
1286          * the actual unfreeze, we can use this to provide an accurate count
1287          * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
1288          * may * be useful for determining whether a filesystem was unfrozen
1289          * during the freeze/thaw phase by a process other than qemu-ga.
1290          */
1291         do {
1292             ret = ioctl(fd, FITHAW);
1293             if (ret == 0 && !logged) {
1294                 i++;
1295                 logged = true;
1296             }
1297         } while (ret == 0);
1298         close(fd);
1299     }
1300 
1301     ga_unset_frozen(ga_state);
1302     free_fs_mount_list(&mounts);
1303 
1304     execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp);
1305 
1306     return i;
1307 }
1308 
1309 static void guest_fsfreeze_cleanup(void)
1310 {
1311     Error *err = NULL;
1312 
1313     if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
1314         qmp_guest_fsfreeze_thaw(&err);
1315         if (err) {
1316             slog("failed to clean up frozen filesystems: %s",
1317                  error_get_pretty(err));
1318             error_free(err);
1319         }
1320     }
1321 }
1322 #endif /* CONFIG_FSFREEZE */
1323 
1324 #if defined(CONFIG_FSTRIM)
1325 /*
1326  * Walk list of mounted file systems in the guest, and trim them.
1327  */
1328 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
1329 {
1330     int ret = 0;
1331     FsMountList mounts;
1332     struct FsMount *mount;
1333     int fd;
1334     Error *local_err = NULL;
1335     struct fstrim_range r = {
1336         .start = 0,
1337         .len = -1,
1338         .minlen = has_minimum ? minimum : 0,
1339     };
1340 
1341     slog("guest-fstrim called");
1342 
1343     QTAILQ_INIT(&mounts);
1344     build_fs_mount_list(&mounts, &local_err);
1345     if (local_err) {
1346         error_propagate(errp, local_err);
1347         return;
1348     }
1349 
1350     QTAILQ_FOREACH(mount, &mounts, next) {
1351         fd = qemu_open(mount->dirname, O_RDONLY);
1352         if (fd == -1) {
1353             error_setg_errno(errp, errno, "failed to open %s", mount->dirname);
1354             goto error;
1355         }
1356 
1357         /* We try to cull filesytems we know won't work in advance, but other
1358          * filesytems may not implement fstrim for less obvious reasons.  These
1359          * will report EOPNOTSUPP; we simply ignore these errors.  Any other
1360          * error means an unexpected error, so return it in those cases.  In
1361          * some other cases ENOTTY will be reported (e.g. CD-ROMs).
1362          */
1363         ret = ioctl(fd, FITRIM, &r);
1364         if (ret == -1) {
1365             if (errno != ENOTTY && errno != EOPNOTSUPP) {
1366                 error_setg_errno(errp, errno, "failed to trim %s",
1367                                  mount->dirname);
1368                 close(fd);
1369                 goto error;
1370             }
1371         }
1372         close(fd);
1373     }
1374 
1375 error:
1376     free_fs_mount_list(&mounts);
1377 }
1378 #endif /* CONFIG_FSTRIM */
1379 
1380 
1381 #define LINUX_SYS_STATE_FILE "/sys/power/state"
1382 #define SUSPEND_SUPPORTED 0
1383 #define SUSPEND_NOT_SUPPORTED 1
1384 
1385 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
1386                                const char *sysfile_str, Error **errp)
1387 {
1388     Error *local_err = NULL;
1389     char *pmutils_path;
1390     pid_t pid;
1391     int status;
1392 
1393     pmutils_path = g_find_program_in_path(pmutils_bin);
1394 
1395     pid = fork();
1396     if (!pid) {
1397         char buf[32]; /* hopefully big enough */
1398         ssize_t ret;
1399         int fd;
1400 
1401         setsid();
1402         reopen_fd_to_null(0);
1403         reopen_fd_to_null(1);
1404         reopen_fd_to_null(2);
1405 
1406         if (pmutils_path) {
1407             execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
1408         }
1409 
1410         /*
1411          * If we get here either pm-utils is not installed or execle() has
1412          * failed. Let's try the manual method if the caller wants it.
1413          */
1414 
1415         if (!sysfile_str) {
1416             _exit(SUSPEND_NOT_SUPPORTED);
1417         }
1418 
1419         fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
1420         if (fd < 0) {
1421             _exit(SUSPEND_NOT_SUPPORTED);
1422         }
1423 
1424         ret = read(fd, buf, sizeof(buf)-1);
1425         if (ret <= 0) {
1426             _exit(SUSPEND_NOT_SUPPORTED);
1427         }
1428         buf[ret] = '\0';
1429 
1430         if (strstr(buf, sysfile_str)) {
1431             _exit(SUSPEND_SUPPORTED);
1432         }
1433 
1434         _exit(SUSPEND_NOT_SUPPORTED);
1435     } else if (pid < 0) {
1436         error_setg_errno(errp, errno, "failed to create child process");
1437         goto out;
1438     }
1439 
1440     ga_wait_child(pid, &status, &local_err);
1441     if (local_err) {
1442         error_propagate(errp, local_err);
1443         goto out;
1444     }
1445 
1446     if (!WIFEXITED(status)) {
1447         error_setg(errp, "child process has terminated abnormally");
1448         goto out;
1449     }
1450 
1451     switch (WEXITSTATUS(status)) {
1452     case SUSPEND_SUPPORTED:
1453         goto out;
1454     case SUSPEND_NOT_SUPPORTED:
1455         error_setg(errp,
1456                    "the requested suspend mode is not supported by the guest");
1457         goto out;
1458     default:
1459         error_setg(errp,
1460                    "the helper program '%s' returned an unexpected exit status"
1461                    " code (%d)", pmutils_path, WEXITSTATUS(status));
1462         goto out;
1463     }
1464 
1465 out:
1466     g_free(pmutils_path);
1467 }
1468 
1469 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
1470                           Error **errp)
1471 {
1472     Error *local_err = NULL;
1473     char *pmutils_path;
1474     pid_t pid;
1475     int status;
1476 
1477     pmutils_path = g_find_program_in_path(pmutils_bin);
1478 
1479     pid = fork();
1480     if (pid == 0) {
1481         /* child */
1482         int fd;
1483 
1484         setsid();
1485         reopen_fd_to_null(0);
1486         reopen_fd_to_null(1);
1487         reopen_fd_to_null(2);
1488 
1489         if (pmutils_path) {
1490             execle(pmutils_path, pmutils_bin, NULL, environ);
1491         }
1492 
1493         /*
1494          * If we get here either pm-utils is not installed or execle() has
1495          * failed. Let's try the manual method if the caller wants it.
1496          */
1497 
1498         if (!sysfile_str) {
1499             _exit(EXIT_FAILURE);
1500         }
1501 
1502         fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
1503         if (fd < 0) {
1504             _exit(EXIT_FAILURE);
1505         }
1506 
1507         if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
1508             _exit(EXIT_FAILURE);
1509         }
1510 
1511         _exit(EXIT_SUCCESS);
1512     } else if (pid < 0) {
1513         error_setg_errno(errp, errno, "failed to create child process");
1514         goto out;
1515     }
1516 
1517     ga_wait_child(pid, &status, &local_err);
1518     if (local_err) {
1519         error_propagate(errp, local_err);
1520         goto out;
1521     }
1522 
1523     if (!WIFEXITED(status)) {
1524         error_setg(errp, "child process has terminated abnormally");
1525         goto out;
1526     }
1527 
1528     if (WEXITSTATUS(status)) {
1529         error_setg(errp, "child process has failed to suspend");
1530         goto out;
1531     }
1532 
1533 out:
1534     g_free(pmutils_path);
1535 }
1536 
1537 void qmp_guest_suspend_disk(Error **errp)
1538 {
1539     Error *local_err = NULL;
1540 
1541     bios_supports_mode("pm-is-supported", "--hibernate", "disk", &local_err);
1542     if (local_err) {
1543         error_propagate(errp, local_err);
1544         return;
1545     }
1546 
1547     guest_suspend("pm-hibernate", "disk", errp);
1548 }
1549 
1550 void qmp_guest_suspend_ram(Error **errp)
1551 {
1552     Error *local_err = NULL;
1553 
1554     bios_supports_mode("pm-is-supported", "--suspend", "mem", &local_err);
1555     if (local_err) {
1556         error_propagate(errp, local_err);
1557         return;
1558     }
1559 
1560     guest_suspend("pm-suspend", "mem", errp);
1561 }
1562 
1563 void qmp_guest_suspend_hybrid(Error **errp)
1564 {
1565     Error *local_err = NULL;
1566 
1567     bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL,
1568                        &local_err);
1569     if (local_err) {
1570         error_propagate(errp, local_err);
1571         return;
1572     }
1573 
1574     guest_suspend("pm-suspend-hybrid", NULL, errp);
1575 }
1576 
1577 static GuestNetworkInterfaceList *
1578 guest_find_interface(GuestNetworkInterfaceList *head,
1579                      const char *name)
1580 {
1581     for (; head; head = head->next) {
1582         if (strcmp(head->value->name, name) == 0) {
1583             break;
1584         }
1585     }
1586 
1587     return head;
1588 }
1589 
1590 /*
1591  * Build information about guest interfaces
1592  */
1593 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
1594 {
1595     GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
1596     struct ifaddrs *ifap, *ifa;
1597 
1598     if (getifaddrs(&ifap) < 0) {
1599         error_setg_errno(errp, errno, "getifaddrs failed");
1600         goto error;
1601     }
1602 
1603     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1604         GuestNetworkInterfaceList *info;
1605         GuestIpAddressList **address_list = NULL, *address_item = NULL;
1606         char addr4[INET_ADDRSTRLEN];
1607         char addr6[INET6_ADDRSTRLEN];
1608         int sock;
1609         struct ifreq ifr;
1610         unsigned char *mac_addr;
1611         void *p;
1612 
1613         g_debug("Processing %s interface", ifa->ifa_name);
1614 
1615         info = guest_find_interface(head, ifa->ifa_name);
1616 
1617         if (!info) {
1618             info = g_malloc0(sizeof(*info));
1619             info->value = g_malloc0(sizeof(*info->value));
1620             info->value->name = g_strdup(ifa->ifa_name);
1621 
1622             if (!cur_item) {
1623                 head = cur_item = info;
1624             } else {
1625                 cur_item->next = info;
1626                 cur_item = info;
1627             }
1628         }
1629 
1630         if (!info->value->has_hardware_address &&
1631             ifa->ifa_flags & SIOCGIFHWADDR) {
1632             /* we haven't obtained HW address yet */
1633             sock = socket(PF_INET, SOCK_STREAM, 0);
1634             if (sock == -1) {
1635                 error_setg_errno(errp, errno, "failed to create socket");
1636                 goto error;
1637             }
1638 
1639             memset(&ifr, 0, sizeof(ifr));
1640             pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
1641             if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
1642                 error_setg_errno(errp, errno,
1643                                  "failed to get MAC address of %s",
1644                                  ifa->ifa_name);
1645                 close(sock);
1646                 goto error;
1647             }
1648 
1649             close(sock);
1650             mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
1651 
1652             info->value->hardware_address =
1653                 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
1654                                 (int) mac_addr[0], (int) mac_addr[1],
1655                                 (int) mac_addr[2], (int) mac_addr[3],
1656                                 (int) mac_addr[4], (int) mac_addr[5]);
1657 
1658             info->value->has_hardware_address = true;
1659         }
1660 
1661         if (ifa->ifa_addr &&
1662             ifa->ifa_addr->sa_family == AF_INET) {
1663             /* interface with IPv4 address */
1664             p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
1665             if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
1666                 error_setg_errno(errp, errno, "inet_ntop failed");
1667                 goto error;
1668             }
1669 
1670             address_item = g_malloc0(sizeof(*address_item));
1671             address_item->value = g_malloc0(sizeof(*address_item->value));
1672             address_item->value->ip_address = g_strdup(addr4);
1673             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
1674 
1675             if (ifa->ifa_netmask) {
1676                 /* Count the number of set bits in netmask.
1677                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
1678                 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
1679                 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
1680             }
1681         } else if (ifa->ifa_addr &&
1682                    ifa->ifa_addr->sa_family == AF_INET6) {
1683             /* interface with IPv6 address */
1684             p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
1685             if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
1686                 error_setg_errno(errp, errno, "inet_ntop failed");
1687                 goto error;
1688             }
1689 
1690             address_item = g_malloc0(sizeof(*address_item));
1691             address_item->value = g_malloc0(sizeof(*address_item->value));
1692             address_item->value->ip_address = g_strdup(addr6);
1693             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
1694 
1695             if (ifa->ifa_netmask) {
1696                 /* Count the number of set bits in netmask.
1697                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
1698                 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
1699                 address_item->value->prefix =
1700                     ctpop32(((uint32_t *) p)[0]) +
1701                     ctpop32(((uint32_t *) p)[1]) +
1702                     ctpop32(((uint32_t *) p)[2]) +
1703                     ctpop32(((uint32_t *) p)[3]);
1704             }
1705         }
1706 
1707         if (!address_item) {
1708             continue;
1709         }
1710 
1711         address_list = &info->value->ip_addresses;
1712 
1713         while (*address_list && (*address_list)->next) {
1714             address_list = &(*address_list)->next;
1715         }
1716 
1717         if (!*address_list) {
1718             *address_list = address_item;
1719         } else {
1720             (*address_list)->next = address_item;
1721         }
1722 
1723         info->value->has_ip_addresses = true;
1724 
1725 
1726     }
1727 
1728     freeifaddrs(ifap);
1729     return head;
1730 
1731 error:
1732     freeifaddrs(ifap);
1733     qapi_free_GuestNetworkInterfaceList(head);
1734     return NULL;
1735 }
1736 
1737 #define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp))
1738 
1739 static long sysconf_exact(int name, const char *name_str, Error **errp)
1740 {
1741     long ret;
1742 
1743     errno = 0;
1744     ret = sysconf(name);
1745     if (ret == -1) {
1746         if (errno == 0) {
1747             error_setg(errp, "sysconf(%s): value indefinite", name_str);
1748         } else {
1749             error_setg_errno(errp, errno, "sysconf(%s)", name_str);
1750         }
1751     }
1752     return ret;
1753 }
1754 
1755 /* Transfer online/offline status between @vcpu and the guest system.
1756  *
1757  * On input either @errp or *@errp must be NULL.
1758  *
1759  * In system-to-@vcpu direction, the following @vcpu fields are accessed:
1760  * - R: vcpu->logical_id
1761  * - W: vcpu->online
1762  * - W: vcpu->can_offline
1763  *
1764  * In @vcpu-to-system direction, the following @vcpu fields are accessed:
1765  * - R: vcpu->logical_id
1766  * - R: vcpu->online
1767  *
1768  * Written members remain unmodified on error.
1769  */
1770 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
1771                           Error **errp)
1772 {
1773     char *dirpath;
1774     int dirfd;
1775 
1776     dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
1777                               vcpu->logical_id);
1778     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
1779     if (dirfd == -1) {
1780         error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
1781     } else {
1782         static const char fn[] = "online";
1783         int fd;
1784         int res;
1785 
1786         fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
1787         if (fd == -1) {
1788             if (errno != ENOENT) {
1789                 error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
1790             } else if (sys2vcpu) {
1791                 vcpu->online = true;
1792                 vcpu->can_offline = false;
1793             } else if (!vcpu->online) {
1794                 error_setg(errp, "logical processor #%" PRId64 " can't be "
1795                            "offlined", vcpu->logical_id);
1796             } /* otherwise pretend successful re-onlining */
1797         } else {
1798             unsigned char status;
1799 
1800             res = pread(fd, &status, 1, 0);
1801             if (res == -1) {
1802                 error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
1803             } else if (res == 0) {
1804                 error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
1805                            fn);
1806             } else if (sys2vcpu) {
1807                 vcpu->online = (status != '0');
1808                 vcpu->can_offline = true;
1809             } else if (vcpu->online != (status != '0')) {
1810                 status = '0' + vcpu->online;
1811                 if (pwrite(fd, &status, 1, 0) == -1) {
1812                     error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
1813                                      fn);
1814                 }
1815             } /* otherwise pretend successful re-(on|off)-lining */
1816 
1817             res = close(fd);
1818             g_assert(res == 0);
1819         }
1820 
1821         res = close(dirfd);
1822         g_assert(res == 0);
1823     }
1824 
1825     g_free(dirpath);
1826 }
1827 
1828 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
1829 {
1830     int64_t current;
1831     GuestLogicalProcessorList *head, **link;
1832     long sc_max;
1833     Error *local_err = NULL;
1834 
1835     current = 0;
1836     head = NULL;
1837     link = &head;
1838     sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err);
1839 
1840     while (local_err == NULL && current < sc_max) {
1841         GuestLogicalProcessor *vcpu;
1842         GuestLogicalProcessorList *entry;
1843 
1844         vcpu = g_malloc0(sizeof *vcpu);
1845         vcpu->logical_id = current++;
1846         vcpu->has_can_offline = true; /* lolspeak ftw */
1847         transfer_vcpu(vcpu, true, &local_err);
1848 
1849         entry = g_malloc0(sizeof *entry);
1850         entry->value = vcpu;
1851 
1852         *link = entry;
1853         link = &entry->next;
1854     }
1855 
1856     if (local_err == NULL) {
1857         /* there's no guest with zero VCPUs */
1858         g_assert(head != NULL);
1859         return head;
1860     }
1861 
1862     qapi_free_GuestLogicalProcessorList(head);
1863     error_propagate(errp, local_err);
1864     return NULL;
1865 }
1866 
1867 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
1868 {
1869     int64_t processed;
1870     Error *local_err = NULL;
1871 
1872     processed = 0;
1873     while (vcpus != NULL) {
1874         transfer_vcpu(vcpus->value, false, &local_err);
1875         if (local_err != NULL) {
1876             break;
1877         }
1878         ++processed;
1879         vcpus = vcpus->next;
1880     }
1881 
1882     if (local_err != NULL) {
1883         if (processed == 0) {
1884             error_propagate(errp, local_err);
1885         } else {
1886             error_free(local_err);
1887         }
1888     }
1889 
1890     return processed;
1891 }
1892 
1893 void qmp_guest_set_user_password(const char *username,
1894                                  const char *password,
1895                                  bool crypted,
1896                                  Error **errp)
1897 {
1898     Error *local_err = NULL;
1899     char *passwd_path = NULL;
1900     pid_t pid;
1901     int status;
1902     int datafd[2] = { -1, -1 };
1903     char *rawpasswddata = NULL;
1904     size_t rawpasswdlen;
1905     char *chpasswddata = NULL;
1906     size_t chpasswdlen;
1907 
1908     rawpasswddata = (char *)g_base64_decode(password, &rawpasswdlen);
1909     rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1);
1910     rawpasswddata[rawpasswdlen] = '\0';
1911 
1912     if (strchr(rawpasswddata, '\n')) {
1913         error_setg(errp, "forbidden characters in raw password");
1914         goto out;
1915     }
1916 
1917     if (strchr(username, '\n') ||
1918         strchr(username, ':')) {
1919         error_setg(errp, "forbidden characters in username");
1920         goto out;
1921     }
1922 
1923     chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata);
1924     chpasswdlen = strlen(chpasswddata);
1925 
1926     passwd_path = g_find_program_in_path("chpasswd");
1927 
1928     if (!passwd_path) {
1929         error_setg(errp, "cannot find 'passwd' program in PATH");
1930         goto out;
1931     }
1932 
1933     if (pipe(datafd) < 0) {
1934         error_setg(errp, "cannot create pipe FDs");
1935         goto out;
1936     }
1937 
1938     pid = fork();
1939     if (pid == 0) {
1940         close(datafd[1]);
1941         /* child */
1942         setsid();
1943         dup2(datafd[0], 0);
1944         reopen_fd_to_null(1);
1945         reopen_fd_to_null(2);
1946 
1947         if (crypted) {
1948             execle(passwd_path, "chpasswd", "-e", NULL, environ);
1949         } else {
1950             execle(passwd_path, "chpasswd", NULL, environ);
1951         }
1952         _exit(EXIT_FAILURE);
1953     } else if (pid < 0) {
1954         error_setg_errno(errp, errno, "failed to create child process");
1955         goto out;
1956     }
1957     close(datafd[0]);
1958     datafd[0] = -1;
1959 
1960     if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) {
1961         error_setg_errno(errp, errno, "cannot write new account password");
1962         goto out;
1963     }
1964     close(datafd[1]);
1965     datafd[1] = -1;
1966 
1967     ga_wait_child(pid, &status, &local_err);
1968     if (local_err) {
1969         error_propagate(errp, local_err);
1970         goto out;
1971     }
1972 
1973     if (!WIFEXITED(status)) {
1974         error_setg(errp, "child process has terminated abnormally");
1975         goto out;
1976     }
1977 
1978     if (WEXITSTATUS(status)) {
1979         error_setg(errp, "child process has failed to set user password");
1980         goto out;
1981     }
1982 
1983 out:
1984     g_free(chpasswddata);
1985     g_free(rawpasswddata);
1986     g_free(passwd_path);
1987     if (datafd[0] != -1) {
1988         close(datafd[0]);
1989     }
1990     if (datafd[1] != -1) {
1991         close(datafd[1]);
1992     }
1993 }
1994 
1995 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf,
1996                                int size, Error **errp)
1997 {
1998     int fd;
1999     int res;
2000 
2001     errno = 0;
2002     fd = openat(dirfd, pathname, O_RDONLY);
2003     if (fd == -1) {
2004         error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
2005         return;
2006     }
2007 
2008     res = pread(fd, buf, size, 0);
2009     if (res == -1) {
2010         error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname);
2011     } else if (res == 0) {
2012         error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname);
2013     }
2014     close(fd);
2015 }
2016 
2017 static void ga_write_sysfs_file(int dirfd, const char *pathname,
2018                                 const char *buf, int size, Error **errp)
2019 {
2020     int fd;
2021 
2022     errno = 0;
2023     fd = openat(dirfd, pathname, O_WRONLY);
2024     if (fd == -1) {
2025         error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
2026         return;
2027     }
2028 
2029     if (pwrite(fd, buf, size, 0) == -1) {
2030         error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname);
2031     }
2032 
2033     close(fd);
2034 }
2035 
2036 /* Transfer online/offline status between @mem_blk and the guest system.
2037  *
2038  * On input either @errp or *@errp must be NULL.
2039  *
2040  * In system-to-@mem_blk direction, the following @mem_blk fields are accessed:
2041  * - R: mem_blk->phys_index
2042  * - W: mem_blk->online
2043  * - W: mem_blk->can_offline
2044  *
2045  * In @mem_blk-to-system direction, the following @mem_blk fields are accessed:
2046  * - R: mem_blk->phys_index
2047  * - R: mem_blk->online
2048  *-  R: mem_blk->can_offline
2049  * Written members remain unmodified on error.
2050  */
2051 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk,
2052                                   GuestMemoryBlockResponse *result,
2053                                   Error **errp)
2054 {
2055     char *dirpath;
2056     int dirfd;
2057     char *status;
2058     Error *local_err = NULL;
2059 
2060     if (!sys2memblk) {
2061         DIR *dp;
2062 
2063         if (!result) {
2064             error_setg(errp, "Internal error, 'result' should not be NULL");
2065             return;
2066         }
2067         errno = 0;
2068         dp = opendir("/sys/devices/system/memory/");
2069          /* if there is no 'memory' directory in sysfs,
2070          * we think this VM does not support online/offline memory block,
2071          * any other solution?
2072          */
2073         if (!dp && errno == ENOENT) {
2074             result->response =
2075                 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
2076             goto out1;
2077         }
2078         closedir(dp);
2079     }
2080 
2081     dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/",
2082                               mem_blk->phys_index);
2083     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
2084     if (dirfd == -1) {
2085         if (sys2memblk) {
2086             error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2087         } else {
2088             if (errno == ENOENT) {
2089                 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND;
2090             } else {
2091                 result->response =
2092                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2093             }
2094         }
2095         g_free(dirpath);
2096         goto out1;
2097     }
2098     g_free(dirpath);
2099 
2100     status = g_malloc0(10);
2101     ga_read_sysfs_file(dirfd, "state", status, 10, &local_err);
2102     if (local_err) {
2103         /* treat with sysfs file that not exist in old kernel */
2104         if (errno == ENOENT) {
2105             error_free(local_err);
2106             if (sys2memblk) {
2107                 mem_blk->online = true;
2108                 mem_blk->can_offline = false;
2109             } else if (!mem_blk->online) {
2110                 result->response =
2111                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
2112             }
2113         } else {
2114             if (sys2memblk) {
2115                 error_propagate(errp, local_err);
2116             } else {
2117                 result->response =
2118                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2119             }
2120         }
2121         goto out2;
2122     }
2123 
2124     if (sys2memblk) {
2125         char removable = '0';
2126 
2127         mem_blk->online = (strncmp(status, "online", 6) == 0);
2128 
2129         ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err);
2130         if (local_err) {
2131             /* if no 'removable' file, it does't support offline mem blk */
2132             if (errno == ENOENT) {
2133                 error_free(local_err);
2134                 mem_blk->can_offline = false;
2135             } else {
2136                 error_propagate(errp, local_err);
2137             }
2138         } else {
2139             mem_blk->can_offline = (removable != '0');
2140         }
2141     } else {
2142         if (mem_blk->online != (strncmp(status, "online", 6) == 0)) {
2143             char *new_state = mem_blk->online ? g_strdup("online") :
2144                                                 g_strdup("offline");
2145 
2146             ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state),
2147                                 &local_err);
2148             g_free(new_state);
2149             if (local_err) {
2150                 error_free(local_err);
2151                 result->response =
2152                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2153                 goto out2;
2154             }
2155 
2156             result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS;
2157             result->has_error_code = false;
2158         } /* otherwise pretend successful re-(on|off)-lining */
2159     }
2160     g_free(status);
2161     close(dirfd);
2162     return;
2163 
2164 out2:
2165     g_free(status);
2166     close(dirfd);
2167 out1:
2168     if (!sys2memblk) {
2169         result->has_error_code = true;
2170         result->error_code = errno;
2171     }
2172 }
2173 
2174 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
2175 {
2176     GuestMemoryBlockList *head, **link;
2177     Error *local_err = NULL;
2178     struct dirent *de;
2179     DIR *dp;
2180 
2181     head = NULL;
2182     link = &head;
2183 
2184     dp = opendir("/sys/devices/system/memory/");
2185     if (!dp) {
2186         error_setg_errno(errp, errno, "Can't open directory"
2187                          "\"/sys/devices/system/memory/\"\n");
2188         return NULL;
2189     }
2190 
2191     /* Note: the phys_index of memory block may be discontinuous,
2192      * this is because a memblk is the unit of the Sparse Memory design, which
2193      * allows discontinuous memory ranges (ex. NUMA), so here we should
2194      * traverse the memory block directory.
2195      */
2196     while ((de = readdir(dp)) != NULL) {
2197         GuestMemoryBlock *mem_blk;
2198         GuestMemoryBlockList *entry;
2199 
2200         if ((strncmp(de->d_name, "memory", 6) != 0) ||
2201             !(de->d_type & DT_DIR)) {
2202             continue;
2203         }
2204 
2205         mem_blk = g_malloc0(sizeof *mem_blk);
2206         /* The d_name is "memoryXXX",  phys_index is block id, same as XXX */
2207         mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10);
2208         mem_blk->has_can_offline = true; /* lolspeak ftw */
2209         transfer_memory_block(mem_blk, true, NULL, &local_err);
2210 
2211         entry = g_malloc0(sizeof *entry);
2212         entry->value = mem_blk;
2213 
2214         *link = entry;
2215         link = &entry->next;
2216     }
2217 
2218     closedir(dp);
2219     if (local_err == NULL) {
2220         /* there's no guest with zero memory blocks */
2221         if (head == NULL) {
2222             error_setg(errp, "guest reported zero memory blocks!");
2223         }
2224         return head;
2225     }
2226 
2227     qapi_free_GuestMemoryBlockList(head);
2228     error_propagate(errp, local_err);
2229     return NULL;
2230 }
2231 
2232 GuestMemoryBlockResponseList *
2233 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
2234 {
2235     GuestMemoryBlockResponseList *head, **link;
2236     Error *local_err = NULL;
2237 
2238     head = NULL;
2239     link = &head;
2240 
2241     while (mem_blks != NULL) {
2242         GuestMemoryBlockResponse *result;
2243         GuestMemoryBlockResponseList *entry;
2244         GuestMemoryBlock *current_mem_blk = mem_blks->value;
2245 
2246         result = g_malloc0(sizeof(*result));
2247         result->phys_index = current_mem_blk->phys_index;
2248         transfer_memory_block(current_mem_blk, false, result, &local_err);
2249         if (local_err) { /* should never happen */
2250             goto err;
2251         }
2252         entry = g_malloc0(sizeof *entry);
2253         entry->value = result;
2254 
2255         *link = entry;
2256         link = &entry->next;
2257         mem_blks = mem_blks->next;
2258     }
2259 
2260     return head;
2261 err:
2262     qapi_free_GuestMemoryBlockResponseList(head);
2263     error_propagate(errp, local_err);
2264     return NULL;
2265 }
2266 
2267 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
2268 {
2269     Error *local_err = NULL;
2270     char *dirpath;
2271     int dirfd;
2272     char *buf;
2273     GuestMemoryBlockInfo *info;
2274 
2275     dirpath = g_strdup_printf("/sys/devices/system/memory/");
2276     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
2277     if (dirfd == -1) {
2278         error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2279         g_free(dirpath);
2280         return NULL;
2281     }
2282     g_free(dirpath);
2283 
2284     buf = g_malloc0(20);
2285     ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err);
2286     if (local_err) {
2287         g_free(buf);
2288         error_propagate(errp, local_err);
2289         return NULL;
2290     }
2291 
2292     info = g_new0(GuestMemoryBlockInfo, 1);
2293     info->size = strtol(buf, NULL, 16); /* the unit is bytes */
2294 
2295     g_free(buf);
2296 
2297     return info;
2298 }
2299 
2300 #else /* defined(__linux__) */
2301 
2302 void qmp_guest_suspend_disk(Error **errp)
2303 {
2304     error_set(errp, QERR_UNSUPPORTED);
2305 }
2306 
2307 void qmp_guest_suspend_ram(Error **errp)
2308 {
2309     error_set(errp, QERR_UNSUPPORTED);
2310 }
2311 
2312 void qmp_guest_suspend_hybrid(Error **errp)
2313 {
2314     error_set(errp, QERR_UNSUPPORTED);
2315 }
2316 
2317 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
2318 {
2319     error_set(errp, QERR_UNSUPPORTED);
2320     return NULL;
2321 }
2322 
2323 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
2324 {
2325     error_set(errp, QERR_UNSUPPORTED);
2326     return NULL;
2327 }
2328 
2329 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
2330 {
2331     error_set(errp, QERR_UNSUPPORTED);
2332     return -1;
2333 }
2334 
2335 void qmp_guest_set_user_password(const char *username,
2336                                  const char *password,
2337                                  bool crypted,
2338                                  Error **errp)
2339 {
2340     error_set(errp, QERR_UNSUPPORTED);
2341 }
2342 
2343 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
2344 {
2345     error_set(errp, QERR_UNSUPPORTED);
2346     return NULL;
2347 }
2348 
2349 GuestMemoryBlockResponseList *
2350 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
2351 {
2352     error_set(errp, QERR_UNSUPPORTED);
2353     return NULL;
2354 }
2355 
2356 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
2357 {
2358     error_set(errp, QERR_UNSUPPORTED);
2359     return NULL;
2360 }
2361 
2362 #endif
2363 
2364 #if !defined(CONFIG_FSFREEZE)
2365 
2366 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
2367 {
2368     error_set(errp, QERR_UNSUPPORTED);
2369     return NULL;
2370 }
2371 
2372 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
2373 {
2374     error_set(errp, QERR_UNSUPPORTED);
2375 
2376     return 0;
2377 }
2378 
2379 int64_t qmp_guest_fsfreeze_freeze(Error **errp)
2380 {
2381     error_set(errp, QERR_UNSUPPORTED);
2382 
2383     return 0;
2384 }
2385 
2386 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
2387                                        strList *mountpoints,
2388                                        Error **errp)
2389 {
2390     error_set(errp, QERR_UNSUPPORTED);
2391 
2392     return 0;
2393 }
2394 
2395 int64_t qmp_guest_fsfreeze_thaw(Error **errp)
2396 {
2397     error_set(errp, QERR_UNSUPPORTED);
2398 
2399     return 0;
2400 }
2401 #endif /* CONFIG_FSFREEZE */
2402 
2403 #if !defined(CONFIG_FSTRIM)
2404 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
2405 {
2406     error_set(errp, QERR_UNSUPPORTED);
2407 }
2408 #endif
2409 
2410 /* add unsupported commands to the blacklist */
2411 GList *ga_command_blacklist_init(GList *blacklist)
2412 {
2413 #if !defined(__linux__)
2414     {
2415         const char *list[] = {
2416             "guest-suspend-disk", "guest-suspend-ram",
2417             "guest-suspend-hybrid", "guest-network-get-interfaces",
2418             "guest-get-vcpus", "guest-set-vcpus",
2419             "guest-get-memory-blocks", "guest-set-memory-blocks",
2420             "guest-get-memory-block-size", NULL};
2421         char **p = (char **)list;
2422 
2423         while (*p) {
2424             blacklist = g_list_append(blacklist, *p++);
2425         }
2426     }
2427 #endif
2428 
2429 #if !defined(CONFIG_FSFREEZE)
2430     {
2431         const char *list[] = {
2432             "guest-get-fsinfo", "guest-fsfreeze-status",
2433             "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list",
2434             "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL};
2435         char **p = (char **)list;
2436 
2437         while (*p) {
2438             blacklist = g_list_append(blacklist, *p++);
2439         }
2440     }
2441 #endif
2442 
2443 #if !defined(CONFIG_FSTRIM)
2444     blacklist = g_list_append(blacklist, (char *)"guest-fstrim");
2445 #endif
2446 
2447     return blacklist;
2448 }
2449 
2450 /* register init/cleanup routines for stateful command groups */
2451 void ga_command_state_init(GAState *s, GACommandState *cs)
2452 {
2453 #if defined(CONFIG_FSFREEZE)
2454     ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
2455 #endif
2456     ga_command_state_add(cs, guest_file_init, NULL);
2457 }
2458