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