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