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