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