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