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