xref: /openbmc/qemu/qga/commands-posix.c (revision d48f61c8)
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 <sys/ioctl.h>
16 #include <sys/utsname.h>
17 #include <sys/wait.h>
18 #include <dirent.h>
19 #include "guest-agent-core.h"
20 #include "qga-qapi-commands.h"
21 #include "qapi/error.h"
22 #include "qapi/qmp/qerror.h"
23 #include "qemu/queue.h"
24 #include "qemu/host-utils.h"
25 #include "qemu/sockets.h"
26 #include "qemu/base64.h"
27 #include "qemu/cutils.h"
28 #include "commands-common.h"
29 
30 #ifdef HAVE_UTMPX
31 #include <utmpx.h>
32 #endif
33 
34 #if defined(__linux__)
35 #include <mntent.h>
36 #include <linux/fs.h>
37 #include <sys/statvfs.h>
38 
39 #ifdef CONFIG_LIBUDEV
40 #include <libudev.h>
41 #endif
42 
43 #ifdef FIFREEZE
44 #define CONFIG_FSFREEZE
45 #endif
46 #ifdef FITRIM
47 #define CONFIG_FSTRIM
48 #endif
49 #endif
50 
51 #ifdef HAVE_GETIFADDRS
52 #include <arpa/inet.h>
53 #include <sys/socket.h>
54 #include <net/if.h>
55 #include <sys/types.h>
56 #include <ifaddrs.h>
57 #ifdef CONFIG_SOLARIS
58 #include <sys/sockio.h>
59 #endif
60 #endif
61 
62 static void ga_wait_child(pid_t pid, int *status, Error **errp)
63 {
64     pid_t rpid;
65 
66     *status = 0;
67 
68     do {
69         rpid = waitpid(pid, status, 0);
70     } while (rpid == -1 && errno == EINTR);
71 
72     if (rpid == -1) {
73         error_setg_errno(errp, errno, "failed to wait for child (pid: %d)",
74                          pid);
75         return;
76     }
77 
78     g_assert(rpid == pid);
79 }
80 
81 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp)
82 {
83     const char *shutdown_flag;
84     Error *local_err = NULL;
85     pid_t pid;
86     int status;
87 
88 #ifdef CONFIG_SOLARIS
89     const char *powerdown_flag = "-i5";
90     const char *halt_flag = "-i0";
91     const char *reboot_flag = "-i6";
92 #else
93     const char *powerdown_flag = "-P";
94     const char *halt_flag = "-H";
95     const char *reboot_flag = "-r";
96 #endif
97 
98     slog("guest-shutdown called, mode: %s", mode);
99     if (!has_mode || strcmp(mode, "powerdown") == 0) {
100         shutdown_flag = powerdown_flag;
101     } else if (strcmp(mode, "halt") == 0) {
102         shutdown_flag = halt_flag;
103     } else if (strcmp(mode, "reboot") == 0) {
104         shutdown_flag = reboot_flag;
105     } else {
106         error_setg(errp,
107                    "mode is invalid (valid values are: halt|powerdown|reboot");
108         return;
109     }
110 
111     pid = fork();
112     if (pid == 0) {
113         /* child, start the shutdown */
114         setsid();
115         reopen_fd_to_null(0);
116         reopen_fd_to_null(1);
117         reopen_fd_to_null(2);
118 
119 #ifdef CONFIG_SOLARIS
120         execl("/sbin/shutdown", "shutdown", shutdown_flag, "-g0", "-y",
121               "hypervisor initiated shutdown", (char *)NULL);
122 #else
123         execl("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0",
124                "hypervisor initiated shutdown", (char *)NULL);
125 #endif
126         _exit(EXIT_FAILURE);
127     } else if (pid < 0) {
128         error_setg_errno(errp, errno, "failed to create child process");
129         return;
130     }
131 
132     ga_wait_child(pid, &status, &local_err);
133     if (local_err) {
134         error_propagate(errp, local_err);
135         return;
136     }
137 
138     if (!WIFEXITED(status)) {
139         error_setg(errp, "child process has terminated abnormally");
140         return;
141     }
142 
143     if (WEXITSTATUS(status)) {
144         error_setg(errp, "child process has failed to shutdown");
145         return;
146     }
147 
148     /* succeeded */
149 }
150 
151 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
152 {
153     int ret;
154     int status;
155     pid_t pid;
156     Error *local_err = NULL;
157     struct timeval tv;
158     static const char hwclock_path[] = "/sbin/hwclock";
159     static int hwclock_available = -1;
160 
161     if (hwclock_available < 0) {
162         hwclock_available = (access(hwclock_path, X_OK) == 0);
163     }
164 
165     if (!hwclock_available) {
166         error_setg(errp, QERR_UNSUPPORTED);
167         return;
168     }
169 
170     /* If user has passed a time, validate and set it. */
171     if (has_time) {
172         GDate date = { 0, };
173 
174         /* year-2038 will overflow in case time_t is 32bit */
175         if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
176             error_setg(errp, "Time %" PRId64 " is too large", time_ns);
177             return;
178         }
179 
180         tv.tv_sec = time_ns / 1000000000;
181         tv.tv_usec = (time_ns % 1000000000) / 1000;
182         g_date_set_time_t(&date, tv.tv_sec);
183         if (date.year < 1970 || date.year >= 2070) {
184             error_setg_errno(errp, errno, "Invalid time");
185             return;
186         }
187 
188         ret = settimeofday(&tv, NULL);
189         if (ret < 0) {
190             error_setg_errno(errp, errno, "Failed to set time to guest");
191             return;
192         }
193     }
194 
195     /* Now, if user has passed a time to set and the system time is set, we
196      * just need to synchronize the hardware clock. However, if no time was
197      * passed, user is requesting the opposite: set the system time from the
198      * hardware clock (RTC). */
199     pid = fork();
200     if (pid == 0) {
201         setsid();
202         reopen_fd_to_null(0);
203         reopen_fd_to_null(1);
204         reopen_fd_to_null(2);
205 
206         /* Use '/sbin/hwclock -w' to set RTC from the system time,
207          * or '/sbin/hwclock -s' to set the system time from RTC. */
208         execl(hwclock_path, "hwclock", has_time ? "-w" : "-s", NULL);
209         _exit(EXIT_FAILURE);
210     } else if (pid < 0) {
211         error_setg_errno(errp, errno, "failed to create child process");
212         return;
213     }
214 
215     ga_wait_child(pid, &status, &local_err);
216     if (local_err) {
217         error_propagate(errp, local_err);
218         return;
219     }
220 
221     if (!WIFEXITED(status)) {
222         error_setg(errp, "child process has terminated abnormally");
223         return;
224     }
225 
226     if (WEXITSTATUS(status)) {
227         error_setg(errp, "hwclock failed to set hardware clock to system time");
228         return;
229     }
230 }
231 
232 typedef enum {
233     RW_STATE_NEW,
234     RW_STATE_READING,
235     RW_STATE_WRITING,
236 } RwState;
237 
238 struct GuestFileHandle {
239     uint64_t id;
240     FILE *fh;
241     RwState state;
242     QTAILQ_ENTRY(GuestFileHandle) next;
243 };
244 
245 static struct {
246     QTAILQ_HEAD(, GuestFileHandle) filehandles;
247 } guest_file_state = {
248     .filehandles = QTAILQ_HEAD_INITIALIZER(guest_file_state.filehandles),
249 };
250 
251 static int64_t guest_file_handle_add(FILE *fh, Error **errp)
252 {
253     GuestFileHandle *gfh;
254     int64_t handle;
255 
256     handle = ga_get_fd_handle(ga_state, errp);
257     if (handle < 0) {
258         return -1;
259     }
260 
261     gfh = g_new0(GuestFileHandle, 1);
262     gfh->id = handle;
263     gfh->fh = fh;
264     QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
265 
266     return handle;
267 }
268 
269 GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp)
270 {
271     GuestFileHandle *gfh;
272 
273     QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
274     {
275         if (gfh->id == id) {
276             return gfh;
277         }
278     }
279 
280     error_setg(errp, "handle '%" PRId64 "' has not been found", id);
281     return NULL;
282 }
283 
284 typedef const char * const ccpc;
285 
286 #ifndef O_BINARY
287 #define O_BINARY 0
288 #endif
289 
290 /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */
291 static const struct {
292     ccpc *forms;
293     int oflag_base;
294 } guest_file_open_modes[] = {
295     { (ccpc[]){ "r",          NULL }, O_RDONLY                                 },
296     { (ccpc[]){ "rb",         NULL }, O_RDONLY                      | O_BINARY },
297     { (ccpc[]){ "w",          NULL }, O_WRONLY | O_CREAT | O_TRUNC             },
298     { (ccpc[]){ "wb",         NULL }, O_WRONLY | O_CREAT | O_TRUNC  | O_BINARY },
299     { (ccpc[]){ "a",          NULL }, O_WRONLY | O_CREAT | O_APPEND            },
300     { (ccpc[]){ "ab",         NULL }, O_WRONLY | O_CREAT | O_APPEND | O_BINARY },
301     { (ccpc[]){ "r+",         NULL }, O_RDWR                                   },
302     { (ccpc[]){ "rb+", "r+b", NULL }, O_RDWR                        | O_BINARY },
303     { (ccpc[]){ "w+",         NULL }, O_RDWR   | O_CREAT | O_TRUNC             },
304     { (ccpc[]){ "wb+", "w+b", NULL }, O_RDWR   | O_CREAT | O_TRUNC  | O_BINARY },
305     { (ccpc[]){ "a+",         NULL }, O_RDWR   | O_CREAT | O_APPEND            },
306     { (ccpc[]){ "ab+", "a+b", NULL }, O_RDWR   | O_CREAT | O_APPEND | O_BINARY }
307 };
308 
309 static int
310 find_open_flag(const char *mode_str, Error **errp)
311 {
312     unsigned mode;
313 
314     for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) {
315         ccpc *form;
316 
317         form = guest_file_open_modes[mode].forms;
318         while (*form != NULL && strcmp(*form, mode_str) != 0) {
319             ++form;
320         }
321         if (*form != NULL) {
322             break;
323         }
324     }
325 
326     if (mode == ARRAY_SIZE(guest_file_open_modes)) {
327         error_setg(errp, "invalid file open mode '%s'", mode_str);
328         return -1;
329     }
330     return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK;
331 }
332 
333 #define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \
334                                S_IRGRP | S_IWGRP | \
335                                S_IROTH | S_IWOTH)
336 
337 static FILE *
338 safe_open_or_create(const char *path, const char *mode, Error **errp)
339 {
340     Error *local_err = NULL;
341     int oflag;
342 
343     oflag = find_open_flag(mode, &local_err);
344     if (local_err == NULL) {
345         int fd;
346 
347         /* If the caller wants / allows creation of a new file, we implement it
348          * with a two step process: open() + (open() / fchmod()).
349          *
350          * First we insist on creating the file exclusively as a new file. If
351          * that succeeds, we're free to set any file-mode bits on it. (The
352          * motivation is that we want to set those file-mode bits independently
353          * of the current umask.)
354          *
355          * If the exclusive creation fails because the file already exists
356          * (EEXIST is not possible for any other reason), we just attempt to
357          * open the file, but in this case we won't be allowed to change the
358          * file-mode bits on the preexistent file.
359          *
360          * The pathname should never disappear between the two open()s in
361          * practice. If it happens, then someone very likely tried to race us.
362          * In this case just go ahead and report the ENOENT from the second
363          * open() to the caller.
364          *
365          * If the caller wants to open a preexistent file, then the first
366          * open() is decisive and its third argument is ignored, and the second
367          * open() and the fchmod() are never called.
368          */
369         fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0);
370         if (fd == -1 && errno == EEXIST) {
371             oflag &= ~(unsigned)O_CREAT;
372             fd = open(path, oflag);
373         }
374 
375         if (fd == -1) {
376             error_setg_errno(&local_err, errno, "failed to open file '%s' "
377                              "(mode: '%s')", path, mode);
378         } else {
379             qemu_set_cloexec(fd);
380 
381             if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) {
382                 error_setg_errno(&local_err, errno, "failed to set permission "
383                                  "0%03o on new file '%s' (mode: '%s')",
384                                  (unsigned)DEFAULT_NEW_FILE_MODE, path, mode);
385             } else {
386                 FILE *f;
387 
388                 f = fdopen(fd, mode);
389                 if (f == NULL) {
390                     error_setg_errno(&local_err, errno, "failed to associate "
391                                      "stdio stream with file descriptor %d, "
392                                      "file '%s' (mode: '%s')", fd, path, mode);
393                 } else {
394                     return f;
395                 }
396             }
397 
398             close(fd);
399             if (oflag & O_CREAT) {
400                 unlink(path);
401             }
402         }
403     }
404 
405     error_propagate(errp, local_err);
406     return NULL;
407 }
408 
409 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode,
410                             Error **errp)
411 {
412     FILE *fh;
413     Error *local_err = NULL;
414     int64_t handle;
415 
416     if (!has_mode) {
417         mode = "r";
418     }
419     slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
420     fh = safe_open_or_create(path, mode, &local_err);
421     if (local_err != NULL) {
422         error_propagate(errp, local_err);
423         return -1;
424     }
425 
426     /* set fd non-blocking to avoid common use cases (like reading from a
427      * named pipe) from hanging the agent
428      */
429     if (!g_unix_set_fd_nonblocking(fileno(fh), true, NULL)) {
430         fclose(fh);
431         error_setg_errno(errp, errno, "Failed to set FD nonblocking");
432         return -1;
433     }
434 
435     handle = guest_file_handle_add(fh, errp);
436     if (handle < 0) {
437         fclose(fh);
438         return -1;
439     }
440 
441     slog("guest-file-open, handle: %" PRId64, handle);
442     return handle;
443 }
444 
445 void qmp_guest_file_close(int64_t handle, Error **errp)
446 {
447     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
448     int ret;
449 
450     slog("guest-file-close called, handle: %" PRId64, handle);
451     if (!gfh) {
452         return;
453     }
454 
455     ret = fclose(gfh->fh);
456     if (ret == EOF) {
457         error_setg_errno(errp, errno, "failed to close handle");
458         return;
459     }
460 
461     QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
462     g_free(gfh);
463 }
464 
465 GuestFileRead *guest_file_read_unsafe(GuestFileHandle *gfh,
466                                       int64_t count, Error **errp)
467 {
468     GuestFileRead *read_data = NULL;
469     guchar *buf;
470     FILE *fh = gfh->fh;
471     size_t read_count;
472 
473     /* explicitly flush when switching from writing to reading */
474     if (gfh->state == RW_STATE_WRITING) {
475         int ret = fflush(fh);
476         if (ret == EOF) {
477             error_setg_errno(errp, errno, "failed to flush file");
478             return NULL;
479         }
480         gfh->state = RW_STATE_NEW;
481     }
482 
483     buf = g_malloc0(count + 1);
484     read_count = fread(buf, 1, count, fh);
485     if (ferror(fh)) {
486         error_setg_errno(errp, errno, "failed to read file");
487     } else {
488         buf[read_count] = 0;
489         read_data = g_new0(GuestFileRead, 1);
490         read_data->count = read_count;
491         read_data->eof = feof(fh);
492         if (read_count) {
493             read_data->buf_b64 = g_base64_encode(buf, read_count);
494         }
495         gfh->state = RW_STATE_READING;
496     }
497     g_free(buf);
498     clearerr(fh);
499 
500     return read_data;
501 }
502 
503 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
504                                      bool has_count, int64_t count,
505                                      Error **errp)
506 {
507     GuestFileWrite *write_data = NULL;
508     guchar *buf;
509     gsize buf_len;
510     int write_count;
511     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
512     FILE *fh;
513 
514     if (!gfh) {
515         return NULL;
516     }
517 
518     fh = gfh->fh;
519 
520     if (gfh->state == RW_STATE_READING) {
521         int ret = fseek(fh, 0, SEEK_CUR);
522         if (ret == -1) {
523             error_setg_errno(errp, errno, "failed to seek file");
524             return NULL;
525         }
526         gfh->state = RW_STATE_NEW;
527     }
528 
529     buf = qbase64_decode(buf_b64, -1, &buf_len, errp);
530     if (!buf) {
531         return NULL;
532     }
533 
534     if (!has_count) {
535         count = buf_len;
536     } else if (count < 0 || count > buf_len) {
537         error_setg(errp, "value '%" PRId64 "' is invalid for argument count",
538                    count);
539         g_free(buf);
540         return NULL;
541     }
542 
543     write_count = fwrite(buf, 1, count, fh);
544     if (ferror(fh)) {
545         error_setg_errno(errp, errno, "failed to write to file");
546         slog("guest-file-write failed, handle: %" PRId64, handle);
547     } else {
548         write_data = g_new0(GuestFileWrite, 1);
549         write_data->count = write_count;
550         write_data->eof = feof(fh);
551         gfh->state = RW_STATE_WRITING;
552     }
553     g_free(buf);
554     clearerr(fh);
555 
556     return write_data;
557 }
558 
559 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
560                                           GuestFileWhence *whence_code,
561                                           Error **errp)
562 {
563     GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
564     GuestFileSeek *seek_data = NULL;
565     FILE *fh;
566     int ret;
567     int whence;
568     Error *err = NULL;
569 
570     if (!gfh) {
571         return NULL;
572     }
573 
574     /* We stupidly exposed 'whence':'int' in our qapi */
575     whence = ga_parse_whence(whence_code, &err);
576     if (err) {
577         error_propagate(errp, err);
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_path_get_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 /*
866  * Store disk device info for devices on the PCI bus.
867  * Returns true if information has been stored, or false for failure.
868  */
869 static bool build_guest_fsinfo_for_pci_dev(char const *syspath,
870                                            GuestDiskAddress *disk,
871                                            Error **errp)
872 {
873     unsigned int pci[4], host, hosts[8], tgt[3];
874     int i, nhosts = 0, pcilen;
875     GuestPCIAddress *pciaddr = disk->pci_controller;
876     bool has_ata = false, has_host = false, has_tgt = false;
877     char *p, *q, *driver = NULL;
878     bool ret = false;
879 
880     p = strstr(syspath, "/devices/pci");
881     if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n",
882                      pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) {
883         g_debug("only pci device is supported: sysfs path '%s'", syspath);
884         return false;
885     }
886 
887     p += 12 + pcilen;
888     while (true) {
889         driver = get_pci_driver(syspath, p - syspath, errp);
890         if (driver && (g_str_equal(driver, "ata_piix") ||
891                        g_str_equal(driver, "sym53c8xx") ||
892                        g_str_equal(driver, "virtio-pci") ||
893                        g_str_equal(driver, "ahci") ||
894                        g_str_equal(driver, "nvme"))) {
895             break;
896         }
897 
898         g_free(driver);
899         if (sscanf(p, "/%x:%x:%x.%x%n",
900                           pci, pci + 1, pci + 2, pci + 3, &pcilen) == 4) {
901             p += pcilen;
902             continue;
903         }
904 
905         g_debug("unsupported driver or sysfs path '%s'", syspath);
906         return false;
907     }
908 
909     p = strstr(syspath, "/target");
910     if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u",
911                     tgt, tgt + 1, tgt + 2) == 3) {
912         has_tgt = true;
913     }
914 
915     p = strstr(syspath, "/ata");
916     if (p) {
917         q = p + 4;
918         has_ata = true;
919     } else {
920         p = strstr(syspath, "/host");
921         q = p + 5;
922     }
923     if (p && sscanf(q, "%u", &host) == 1) {
924         has_host = true;
925         nhosts = build_hosts(syspath, p, has_ata, hosts,
926                              ARRAY_SIZE(hosts), errp);
927         if (nhosts < 0) {
928             goto cleanup;
929         }
930     }
931 
932     pciaddr->domain = pci[0];
933     pciaddr->bus = pci[1];
934     pciaddr->slot = pci[2];
935     pciaddr->function = pci[3];
936 
937     if (strcmp(driver, "ata_piix") == 0) {
938         /* a host per ide bus, target*:0:<unit>:0 */
939         if (!has_host || !has_tgt) {
940             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
941             goto cleanup;
942         }
943         for (i = 0; i < nhosts; i++) {
944             if (host == hosts[i]) {
945                 disk->bus_type = GUEST_DISK_BUS_TYPE_IDE;
946                 disk->bus = i;
947                 disk->unit = tgt[1];
948                 break;
949             }
950         }
951         if (i >= nhosts) {
952             g_debug("no host for '%s' (driver '%s')", syspath, driver);
953             goto cleanup;
954         }
955     } else if (strcmp(driver, "sym53c8xx") == 0) {
956         /* scsi(LSI Logic): target*:0:<unit>:0 */
957         if (!has_tgt) {
958             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
959             goto cleanup;
960         }
961         disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
962         disk->unit = tgt[1];
963     } else if (strcmp(driver, "virtio-pci") == 0) {
964         if (has_tgt) {
965             /* virtio-scsi: target*:0:0:<unit> */
966             disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
967             disk->unit = tgt[2];
968         } else {
969             /* virtio-blk: 1 disk per 1 device */
970             disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO;
971         }
972     } else if (strcmp(driver, "ahci") == 0) {
973         /* ahci: 1 host per 1 unit */
974         if (!has_host || !has_tgt) {
975             g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
976             goto cleanup;
977         }
978         for (i = 0; i < nhosts; i++) {
979             if (host == hosts[i]) {
980                 disk->unit = i;
981                 disk->bus_type = GUEST_DISK_BUS_TYPE_SATA;
982                 break;
983             }
984         }
985         if (i >= nhosts) {
986             g_debug("no host for '%s' (driver '%s')", syspath, driver);
987             goto cleanup;
988         }
989     } else if (strcmp(driver, "nvme") == 0) {
990         disk->bus_type = GUEST_DISK_BUS_TYPE_NVME;
991     } else {
992         g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath);
993         goto cleanup;
994     }
995 
996     ret = true;
997 
998 cleanup:
999     g_free(driver);
1000     return ret;
1001 }
1002 
1003 /*
1004  * Store disk device info for non-PCI virtio devices (for example s390x
1005  * channel I/O devices). Returns true if information has been stored, or
1006  * false for failure.
1007  */
1008 static bool build_guest_fsinfo_for_nonpci_virtio(char const *syspath,
1009                                                  GuestDiskAddress *disk,
1010                                                  Error **errp)
1011 {
1012     unsigned int tgt[3];
1013     char *p;
1014 
1015     if (!strstr(syspath, "/virtio") || !strstr(syspath, "/block")) {
1016         g_debug("Unsupported virtio device '%s'", syspath);
1017         return false;
1018     }
1019 
1020     p = strstr(syspath, "/target");
1021     if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u",
1022                     &tgt[0], &tgt[1], &tgt[2]) == 3) {
1023         /* virtio-scsi: target*:0:<target>:<unit> */
1024         disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
1025         disk->bus = tgt[0];
1026         disk->target = tgt[1];
1027         disk->unit = tgt[2];
1028     } else {
1029         /* virtio-blk: 1 disk per 1 device */
1030         disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO;
1031     }
1032 
1033     return true;
1034 }
1035 
1036 /*
1037  * Store disk device info for CCW devices (s390x channel I/O devices).
1038  * Returns true if information has been stored, or false for failure.
1039  */
1040 static bool build_guest_fsinfo_for_ccw_dev(char const *syspath,
1041                                            GuestDiskAddress *disk,
1042                                            Error **errp)
1043 {
1044     unsigned int cssid, ssid, subchno, devno;
1045     char *p;
1046 
1047     p = strstr(syspath, "/devices/css");
1048     if (!p || sscanf(p + 12, "%*x/%x.%x.%x/%*x.%*x.%x/",
1049                      &cssid, &ssid, &subchno, &devno) < 4) {
1050         g_debug("could not parse ccw device sysfs path: %s", syspath);
1051         return false;
1052     }
1053 
1054     disk->has_ccw_address = true;
1055     disk->ccw_address = g_new0(GuestCCWAddress, 1);
1056     disk->ccw_address->cssid = cssid;
1057     disk->ccw_address->ssid = ssid;
1058     disk->ccw_address->subchno = subchno;
1059     disk->ccw_address->devno = devno;
1060 
1061     if (strstr(p, "/virtio")) {
1062         build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
1063     }
1064 
1065     return true;
1066 }
1067 
1068 /* Store disk device info specified by @sysfs into @fs */
1069 static void build_guest_fsinfo_for_real_device(char const *syspath,
1070                                                GuestFilesystemInfo *fs,
1071                                                Error **errp)
1072 {
1073     GuestDiskAddress *disk;
1074     GuestPCIAddress *pciaddr;
1075     bool has_hwinf;
1076 #ifdef CONFIG_LIBUDEV
1077     struct udev *udev = NULL;
1078     struct udev_device *udevice = NULL;
1079 #endif
1080 
1081     pciaddr = g_new0(GuestPCIAddress, 1);
1082     pciaddr->domain = -1;                       /* -1 means field is invalid */
1083     pciaddr->bus = -1;
1084     pciaddr->slot = -1;
1085     pciaddr->function = -1;
1086 
1087     disk = g_new0(GuestDiskAddress, 1);
1088     disk->pci_controller = pciaddr;
1089     disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
1090 
1091 #ifdef CONFIG_LIBUDEV
1092     udev = udev_new();
1093     udevice = udev_device_new_from_syspath(udev, syspath);
1094     if (udev == NULL || udevice == NULL) {
1095         g_debug("failed to query udev");
1096     } else {
1097         const char *devnode, *serial;
1098         devnode = udev_device_get_devnode(udevice);
1099         if (devnode != NULL) {
1100             disk->dev = g_strdup(devnode);
1101             disk->has_dev = true;
1102         }
1103         serial = udev_device_get_property_value(udevice, "ID_SERIAL");
1104         if (serial != NULL && *serial != 0) {
1105             disk->serial = g_strdup(serial);
1106             disk->has_serial = true;
1107         }
1108     }
1109 
1110     udev_unref(udev);
1111     udev_device_unref(udevice);
1112 #endif
1113 
1114     if (strstr(syspath, "/devices/pci")) {
1115         has_hwinf = build_guest_fsinfo_for_pci_dev(syspath, disk, errp);
1116     } else if (strstr(syspath, "/devices/css")) {
1117         has_hwinf = build_guest_fsinfo_for_ccw_dev(syspath, disk, errp);
1118     } else if (strstr(syspath, "/virtio")) {
1119         has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
1120     } else {
1121         g_debug("Unsupported device type for '%s'", syspath);
1122         has_hwinf = false;
1123     }
1124 
1125     if (has_hwinf || disk->has_dev || disk->has_serial) {
1126         QAPI_LIST_PREPEND(fs->disk, disk);
1127     } else {
1128         qapi_free_GuestDiskAddress(disk);
1129     }
1130 }
1131 
1132 static void build_guest_fsinfo_for_device(char const *devpath,
1133                                           GuestFilesystemInfo *fs,
1134                                           Error **errp);
1135 
1136 /* Store a list of slave devices of virtual volume specified by @syspath into
1137  * @fs */
1138 static void build_guest_fsinfo_for_virtual_device(char const *syspath,
1139                                                   GuestFilesystemInfo *fs,
1140                                                   Error **errp)
1141 {
1142     Error *err = NULL;
1143     DIR *dir;
1144     char *dirpath;
1145     struct dirent *entry;
1146 
1147     dirpath = g_strdup_printf("%s/slaves", syspath);
1148     dir = opendir(dirpath);
1149     if (!dir) {
1150         if (errno != ENOENT) {
1151             error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath);
1152         }
1153         g_free(dirpath);
1154         return;
1155     }
1156 
1157     for (;;) {
1158         errno = 0;
1159         entry = readdir(dir);
1160         if (entry == NULL) {
1161             if (errno) {
1162                 error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath);
1163             }
1164             break;
1165         }
1166 
1167         if (entry->d_type == DT_LNK) {
1168             char *path;
1169 
1170             g_debug(" slave device '%s'", entry->d_name);
1171             path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name);
1172             build_guest_fsinfo_for_device(path, fs, &err);
1173             g_free(path);
1174 
1175             if (err) {
1176                 error_propagate(errp, err);
1177                 break;
1178             }
1179         }
1180     }
1181 
1182     g_free(dirpath);
1183     closedir(dir);
1184 }
1185 
1186 static bool is_disk_virtual(const char *devpath, Error **errp)
1187 {
1188     g_autofree char *syspath = realpath(devpath, NULL);
1189 
1190     if (!syspath) {
1191         error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
1192         return false;
1193     }
1194     return strstr(syspath, "/devices/virtual/block/") != NULL;
1195 }
1196 
1197 /* Dispatch to functions for virtual/real device */
1198 static void build_guest_fsinfo_for_device(char const *devpath,
1199                                           GuestFilesystemInfo *fs,
1200                                           Error **errp)
1201 {
1202     ERRP_GUARD();
1203     g_autofree char *syspath = NULL;
1204     bool is_virtual = false;
1205 
1206     syspath = realpath(devpath, NULL);
1207     if (!syspath) {
1208         error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
1209         return;
1210     }
1211 
1212     if (!fs->name) {
1213         fs->name = g_path_get_basename(syspath);
1214     }
1215 
1216     g_debug("  parse sysfs path '%s'", syspath);
1217     is_virtual = is_disk_virtual(syspath, errp);
1218     if (*errp != NULL) {
1219         return;
1220     }
1221     if (is_virtual) {
1222         build_guest_fsinfo_for_virtual_device(syspath, fs, errp);
1223     } else {
1224         build_guest_fsinfo_for_real_device(syspath, fs, errp);
1225     }
1226 }
1227 
1228 #ifdef CONFIG_LIBUDEV
1229 
1230 /*
1231  * Wrapper around build_guest_fsinfo_for_device() for getting just
1232  * the disk address.
1233  */
1234 static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp)
1235 {
1236     g_autoptr(GuestFilesystemInfo) fs = NULL;
1237 
1238     fs = g_new0(GuestFilesystemInfo, 1);
1239     build_guest_fsinfo_for_device(syspath, fs, errp);
1240     if (fs->disk != NULL) {
1241         return g_steal_pointer(&fs->disk->value);
1242     }
1243     return NULL;
1244 }
1245 
1246 static char *get_alias_for_syspath(const char *syspath)
1247 {
1248     struct udev *udev = NULL;
1249     struct udev_device *udevice = NULL;
1250     char *ret = NULL;
1251 
1252     udev = udev_new();
1253     if (udev == NULL) {
1254         g_debug("failed to query udev");
1255         goto out;
1256     }
1257     udevice = udev_device_new_from_syspath(udev, syspath);
1258     if (udevice == NULL) {
1259         g_debug("failed to query udev for path: %s", syspath);
1260         goto out;
1261     } else {
1262         const char *alias = udev_device_get_property_value(
1263             udevice, "DM_NAME");
1264         /*
1265          * NULL means there was an error and empty string means there is no
1266          * alias. In case of no alias we return NULL instead of empty string.
1267          */
1268         if (alias == NULL) {
1269             g_debug("failed to query udev for device alias for: %s",
1270                 syspath);
1271         } else if (*alias != 0) {
1272             ret = g_strdup(alias);
1273         }
1274     }
1275 
1276 out:
1277     udev_unref(udev);
1278     udev_device_unref(udevice);
1279     return ret;
1280 }
1281 
1282 static char *get_device_for_syspath(const char *syspath)
1283 {
1284     struct udev *udev = NULL;
1285     struct udev_device *udevice = NULL;
1286     char *ret = NULL;
1287 
1288     udev = udev_new();
1289     if (udev == NULL) {
1290         g_debug("failed to query udev");
1291         goto out;
1292     }
1293     udevice = udev_device_new_from_syspath(udev, syspath);
1294     if (udevice == NULL) {
1295         g_debug("failed to query udev for path: %s", syspath);
1296         goto out;
1297     } else {
1298         ret = g_strdup(udev_device_get_devnode(udevice));
1299     }
1300 
1301 out:
1302     udev_unref(udev);
1303     udev_device_unref(udevice);
1304     return ret;
1305 }
1306 
1307 static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
1308 {
1309     g_autofree char *deps_dir = NULL;
1310     const gchar *dep;
1311     GDir *dp_deps = NULL;
1312 
1313     /* List dependent disks */
1314     deps_dir = g_strdup_printf("%s/slaves", disk_dir);
1315     g_debug("  listing entries in: %s", deps_dir);
1316     dp_deps = g_dir_open(deps_dir, 0, NULL);
1317     if (dp_deps == NULL) {
1318         g_debug("failed to list entries in %s", deps_dir);
1319         return;
1320     }
1321     disk->has_dependencies = true;
1322     while ((dep = g_dir_read_name(dp_deps)) != NULL) {
1323         g_autofree char *dep_dir = NULL;
1324         char *dev_name;
1325 
1326         /* Add dependent disks */
1327         dep_dir = g_strdup_printf("%s/%s", deps_dir, dep);
1328         dev_name = get_device_for_syspath(dep_dir);
1329         if (dev_name != NULL) {
1330             g_debug("  adding dependent device: %s", dev_name);
1331             QAPI_LIST_PREPEND(disk->dependencies, dev_name);
1332         }
1333     }
1334     g_dir_close(dp_deps);
1335 }
1336 
1337 /*
1338  * Detect partitions subdirectory, name is "<disk_name><number>" or
1339  * "<disk_name>p<number>"
1340  *
1341  * @disk_name -- last component of /sys path (e.g. sda)
1342  * @disk_dir -- sys path of the disk (e.g. /sys/block/sda)
1343  * @disk_dev -- device node of the disk (e.g. /dev/sda)
1344  */
1345 static GuestDiskInfoList *get_disk_partitions(
1346     GuestDiskInfoList *list,
1347     const char *disk_name, const char *disk_dir,
1348     const char *disk_dev)
1349 {
1350     GuestDiskInfoList *ret = list;
1351     struct dirent *de_disk;
1352     DIR *dp_disk = NULL;
1353     size_t len = strlen(disk_name);
1354 
1355     dp_disk = opendir(disk_dir);
1356     while ((de_disk = readdir(dp_disk)) != NULL) {
1357         g_autofree char *partition_dir = NULL;
1358         char *dev_name;
1359         GuestDiskInfo *partition;
1360 
1361         if (!(de_disk->d_type & DT_DIR)) {
1362             continue;
1363         }
1364 
1365         if (!(strncmp(disk_name, de_disk->d_name, len) == 0 &&
1366             ((*(de_disk->d_name + len) == 'p' &&
1367             isdigit(*(de_disk->d_name + len + 1))) ||
1368                 isdigit(*(de_disk->d_name + len))))) {
1369             continue;
1370         }
1371 
1372         partition_dir = g_strdup_printf("%s/%s",
1373             disk_dir, de_disk->d_name);
1374         dev_name = get_device_for_syspath(partition_dir);
1375         if (dev_name == NULL) {
1376             g_debug("Failed to get device name for syspath: %s",
1377                 disk_dir);
1378             continue;
1379         }
1380         partition = g_new0(GuestDiskInfo, 1);
1381         partition->name = dev_name;
1382         partition->partition = true;
1383         partition->has_dependencies = true;
1384         /* Add parent disk as dependent for easier tracking of hierarchy */
1385         QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev));
1386 
1387         QAPI_LIST_PREPEND(ret, partition);
1388     }
1389     closedir(dp_disk);
1390 
1391     return ret;
1392 }
1393 
1394 GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
1395 {
1396     GuestDiskInfoList *ret = NULL;
1397     GuestDiskInfo *disk;
1398     DIR *dp = NULL;
1399     struct dirent *de = NULL;
1400 
1401     g_debug("listing /sys/block directory");
1402     dp = opendir("/sys/block");
1403     if (dp == NULL) {
1404         error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"");
1405         return NULL;
1406     }
1407     while ((de = readdir(dp)) != NULL) {
1408         g_autofree char *disk_dir = NULL, *line = NULL,
1409             *size_path = NULL;
1410         char *dev_name;
1411         Error *local_err = NULL;
1412         if (de->d_type != DT_LNK) {
1413             g_debug("  skipping entry: %s", de->d_name);
1414             continue;
1415         }
1416 
1417         /* Check size and skip zero-sized disks */
1418         g_debug("  checking disk size");
1419         size_path = g_strdup_printf("/sys/block/%s/size", de->d_name);
1420         if (!g_file_get_contents(size_path, &line, NULL, NULL)) {
1421             g_debug("  failed to read disk size");
1422             continue;
1423         }
1424         if (g_strcmp0(line, "0\n") == 0) {
1425             g_debug("  skipping zero-sized disk");
1426             continue;
1427         }
1428 
1429         g_debug("  adding %s", de->d_name);
1430         disk_dir = g_strdup_printf("/sys/block/%s", de->d_name);
1431         dev_name = get_device_for_syspath(disk_dir);
1432         if (dev_name == NULL) {
1433             g_debug("Failed to get device name for syspath: %s",
1434                 disk_dir);
1435             continue;
1436         }
1437         disk = g_new0(GuestDiskInfo, 1);
1438         disk->name = dev_name;
1439         disk->partition = false;
1440         disk->alias = get_alias_for_syspath(disk_dir);
1441         disk->has_alias = (disk->alias != NULL);
1442         QAPI_LIST_PREPEND(ret, disk);
1443 
1444         /* Get address for non-virtual devices */
1445         bool is_virtual = is_disk_virtual(disk_dir, &local_err);
1446         if (local_err != NULL) {
1447             g_debug("  failed to check disk path, ignoring error: %s",
1448                 error_get_pretty(local_err));
1449             error_free(local_err);
1450             local_err = NULL;
1451             /* Don't try to get the address */
1452             is_virtual = true;
1453         }
1454         if (!is_virtual) {
1455             disk->address = get_disk_address(disk_dir, &local_err);
1456             if (local_err != NULL) {
1457                 g_debug("  failed to get device info, ignoring error: %s",
1458                     error_get_pretty(local_err));
1459                 error_free(local_err);
1460                 local_err = NULL;
1461             } else if (disk->address != NULL) {
1462                 disk->has_address = true;
1463             }
1464         }
1465 
1466         get_disk_deps(disk_dir, disk);
1467         ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name);
1468     }
1469 
1470     closedir(dp);
1471 
1472     return ret;
1473 }
1474 
1475 #else
1476 
1477 GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
1478 {
1479     error_setg(errp, QERR_UNSUPPORTED);
1480     return NULL;
1481 }
1482 
1483 #endif
1484 
1485 /* Return a list of the disk device(s)' info which @mount lies on */
1486 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount,
1487                                                Error **errp)
1488 {
1489     GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs));
1490     struct statvfs buf;
1491     unsigned long used, nonroot_total, fr_size;
1492     char *devpath = g_strdup_printf("/sys/dev/block/%u:%u",
1493                                     mount->devmajor, mount->devminor);
1494 
1495     fs->mountpoint = g_strdup(mount->dirname);
1496     fs->type = g_strdup(mount->devtype);
1497     build_guest_fsinfo_for_device(devpath, fs, errp);
1498 
1499     if (statvfs(fs->mountpoint, &buf) == 0) {
1500         fr_size = buf.f_frsize;
1501         used = buf.f_blocks - buf.f_bfree;
1502         nonroot_total = used + buf.f_bavail;
1503         fs->used_bytes = used * fr_size;
1504         fs->total_bytes = nonroot_total * fr_size;
1505 
1506         fs->has_total_bytes = true;
1507         fs->has_used_bytes = true;
1508     }
1509 
1510     g_free(devpath);
1511 
1512     return fs;
1513 }
1514 
1515 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
1516 {
1517     FsMountList mounts;
1518     struct FsMount *mount;
1519     GuestFilesystemInfoList *ret = NULL;
1520     Error *local_err = NULL;
1521 
1522     QTAILQ_INIT(&mounts);
1523     build_fs_mount_list(&mounts, &local_err);
1524     if (local_err) {
1525         error_propagate(errp, local_err);
1526         return NULL;
1527     }
1528 
1529     QTAILQ_FOREACH(mount, &mounts, next) {
1530         g_debug("Building guest fsinfo for '%s'", mount->dirname);
1531 
1532         QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
1533         if (local_err) {
1534             error_propagate(errp, local_err);
1535             qapi_free_GuestFilesystemInfoList(ret);
1536             ret = NULL;
1537             break;
1538         }
1539     }
1540 
1541     free_fs_mount_list(&mounts);
1542     return ret;
1543 }
1544 
1545 
1546 typedef enum {
1547     FSFREEZE_HOOK_THAW = 0,
1548     FSFREEZE_HOOK_FREEZE,
1549 } FsfreezeHookArg;
1550 
1551 static const char *fsfreeze_hook_arg_string[] = {
1552     "thaw",
1553     "freeze",
1554 };
1555 
1556 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp)
1557 {
1558     int status;
1559     pid_t pid;
1560     const char *hook;
1561     const char *arg_str = fsfreeze_hook_arg_string[arg];
1562     Error *local_err = NULL;
1563 
1564     hook = ga_fsfreeze_hook(ga_state);
1565     if (!hook) {
1566         return;
1567     }
1568     if (access(hook, X_OK) != 0) {
1569         error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook);
1570         return;
1571     }
1572 
1573     slog("executing fsfreeze hook with arg '%s'", arg_str);
1574     pid = fork();
1575     if (pid == 0) {
1576         setsid();
1577         reopen_fd_to_null(0);
1578         reopen_fd_to_null(1);
1579         reopen_fd_to_null(2);
1580 
1581         execl(hook, hook, arg_str, NULL);
1582         _exit(EXIT_FAILURE);
1583     } else if (pid < 0) {
1584         error_setg_errno(errp, errno, "failed to create child process");
1585         return;
1586     }
1587 
1588     ga_wait_child(pid, &status, &local_err);
1589     if (local_err) {
1590         error_propagate(errp, local_err);
1591         return;
1592     }
1593 
1594     if (!WIFEXITED(status)) {
1595         error_setg(errp, "fsfreeze hook has terminated abnormally");
1596         return;
1597     }
1598 
1599     status = WEXITSTATUS(status);
1600     if (status) {
1601         error_setg(errp, "fsfreeze hook has failed with status %d", status);
1602         return;
1603     }
1604 }
1605 
1606 /*
1607  * Return status of freeze/thaw
1608  */
1609 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
1610 {
1611     if (ga_is_frozen(ga_state)) {
1612         return GUEST_FSFREEZE_STATUS_FROZEN;
1613     }
1614 
1615     return GUEST_FSFREEZE_STATUS_THAWED;
1616 }
1617 
1618 int64_t qmp_guest_fsfreeze_freeze(Error **errp)
1619 {
1620     return qmp_guest_fsfreeze_freeze_list(false, NULL, errp);
1621 }
1622 
1623 /*
1624  * Walk list of mounted file systems in the guest, and freeze the ones which
1625  * are real local file systems.
1626  */
1627 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
1628                                        strList *mountpoints,
1629                                        Error **errp)
1630 {
1631     int ret = 0, i = 0;
1632     strList *list;
1633     FsMountList mounts;
1634     struct FsMount *mount;
1635     Error *local_err = NULL;
1636     int fd;
1637 
1638     slog("guest-fsfreeze called");
1639 
1640     execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
1641     if (local_err) {
1642         error_propagate(errp, local_err);
1643         return -1;
1644     }
1645 
1646     QTAILQ_INIT(&mounts);
1647     build_fs_mount_list(&mounts, &local_err);
1648     if (local_err) {
1649         error_propagate(errp, local_err);
1650         return -1;
1651     }
1652 
1653     /* cannot risk guest agent blocking itself on a write in this state */
1654     ga_set_frozen(ga_state);
1655 
1656     QTAILQ_FOREACH_REVERSE(mount, &mounts, next) {
1657         /* To issue fsfreeze in the reverse order of mounts, check if the
1658          * mount is listed in the list here */
1659         if (has_mountpoints) {
1660             for (list = mountpoints; list; list = list->next) {
1661                 if (strcmp(list->value, mount->dirname) == 0) {
1662                     break;
1663                 }
1664             }
1665             if (!list) {
1666                 continue;
1667             }
1668         }
1669 
1670         fd = qemu_open_old(mount->dirname, O_RDONLY);
1671         if (fd == -1) {
1672             error_setg_errno(errp, errno, "failed to open %s", mount->dirname);
1673             goto error;
1674         }
1675 
1676         /* we try to cull filesystems we know won't work in advance, but other
1677          * filesystems may not implement fsfreeze for less obvious reasons.
1678          * these will report EOPNOTSUPP. we simply ignore these when tallying
1679          * the number of frozen filesystems.
1680          * if a filesystem is mounted more than once (aka bind mount) a
1681          * consecutive attempt to freeze an already frozen filesystem will
1682          * return EBUSY.
1683          *
1684          * any other error means a failure to freeze a filesystem we
1685          * expect to be freezable, so return an error in those cases
1686          * and return system to thawed state.
1687          */
1688         ret = ioctl(fd, FIFREEZE);
1689         if (ret == -1) {
1690             if (errno != EOPNOTSUPP && errno != EBUSY) {
1691                 error_setg_errno(errp, errno, "failed to freeze %s",
1692                                  mount->dirname);
1693                 close(fd);
1694                 goto error;
1695             }
1696         } else {
1697             i++;
1698         }
1699         close(fd);
1700     }
1701 
1702     free_fs_mount_list(&mounts);
1703     /* We may not issue any FIFREEZE here.
1704      * Just unset ga_state here and ready for the next call.
1705      */
1706     if (i == 0) {
1707         ga_unset_frozen(ga_state);
1708     }
1709     return i;
1710 
1711 error:
1712     free_fs_mount_list(&mounts);
1713     qmp_guest_fsfreeze_thaw(NULL);
1714     return 0;
1715 }
1716 
1717 /*
1718  * Walk list of frozen file systems in the guest, and thaw them.
1719  */
1720 int64_t qmp_guest_fsfreeze_thaw(Error **errp)
1721 {
1722     int ret;
1723     FsMountList mounts;
1724     FsMount *mount;
1725     int fd, i = 0, logged;
1726     Error *local_err = NULL;
1727 
1728     QTAILQ_INIT(&mounts);
1729     build_fs_mount_list(&mounts, &local_err);
1730     if (local_err) {
1731         error_propagate(errp, local_err);
1732         return 0;
1733     }
1734 
1735     QTAILQ_FOREACH(mount, &mounts, next) {
1736         logged = false;
1737         fd = qemu_open_old(mount->dirname, O_RDONLY);
1738         if (fd == -1) {
1739             continue;
1740         }
1741         /* we have no way of knowing whether a filesystem was actually unfrozen
1742          * as a result of a successful call to FITHAW, only that if an error
1743          * was returned the filesystem was *not* unfrozen by that particular
1744          * call.
1745          *
1746          * since multiple preceding FIFREEZEs require multiple calls to FITHAW
1747          * to unfreeze, continuing issuing FITHAW until an error is returned,
1748          * in which case either the filesystem is in an unfreezable state, or,
1749          * more likely, it was thawed previously (and remains so afterward).
1750          *
1751          * also, since the most recent successful call is the one that did
1752          * the actual unfreeze, we can use this to provide an accurate count
1753          * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
1754          * may * be useful for determining whether a filesystem was unfrozen
1755          * during the freeze/thaw phase by a process other than qemu-ga.
1756          */
1757         do {
1758             ret = ioctl(fd, FITHAW);
1759             if (ret == 0 && !logged) {
1760                 i++;
1761                 logged = true;
1762             }
1763         } while (ret == 0);
1764         close(fd);
1765     }
1766 
1767     ga_unset_frozen(ga_state);
1768     free_fs_mount_list(&mounts);
1769 
1770     execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp);
1771 
1772     return i;
1773 }
1774 
1775 static void guest_fsfreeze_cleanup(void)
1776 {
1777     Error *err = NULL;
1778 
1779     if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
1780         qmp_guest_fsfreeze_thaw(&err);
1781         if (err) {
1782             slog("failed to clean up frozen filesystems: %s",
1783                  error_get_pretty(err));
1784             error_free(err);
1785         }
1786     }
1787 }
1788 #endif /* CONFIG_FSFREEZE */
1789 
1790 #if defined(CONFIG_FSTRIM)
1791 /*
1792  * Walk list of mounted file systems in the guest, and trim them.
1793  */
1794 GuestFilesystemTrimResponse *
1795 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
1796 {
1797     GuestFilesystemTrimResponse *response;
1798     GuestFilesystemTrimResult *result;
1799     int ret = 0;
1800     FsMountList mounts;
1801     struct FsMount *mount;
1802     int fd;
1803     Error *local_err = NULL;
1804     struct fstrim_range r;
1805 
1806     slog("guest-fstrim called");
1807 
1808     QTAILQ_INIT(&mounts);
1809     build_fs_mount_list(&mounts, &local_err);
1810     if (local_err) {
1811         error_propagate(errp, local_err);
1812         return NULL;
1813     }
1814 
1815     response = g_malloc0(sizeof(*response));
1816 
1817     QTAILQ_FOREACH(mount, &mounts, next) {
1818         result = g_malloc0(sizeof(*result));
1819         result->path = g_strdup(mount->dirname);
1820 
1821         QAPI_LIST_PREPEND(response->paths, result);
1822 
1823         fd = qemu_open_old(mount->dirname, O_RDONLY);
1824         if (fd == -1) {
1825             result->error = g_strdup_printf("failed to open: %s",
1826                                             strerror(errno));
1827             result->has_error = true;
1828             continue;
1829         }
1830 
1831         /* We try to cull filesystems we know won't work in advance, but other
1832          * filesystems may not implement fstrim for less obvious reasons.
1833          * These will report EOPNOTSUPP; while in some other cases ENOTTY
1834          * will be reported (e.g. CD-ROMs).
1835          * Any other error means an unexpected error.
1836          */
1837         r.start = 0;
1838         r.len = -1;
1839         r.minlen = has_minimum ? minimum : 0;
1840         ret = ioctl(fd, FITRIM, &r);
1841         if (ret == -1) {
1842             result->has_error = true;
1843             if (errno == ENOTTY || errno == EOPNOTSUPP) {
1844                 result->error = g_strdup("trim not supported");
1845             } else {
1846                 result->error = g_strdup_printf("failed to trim: %s",
1847                                                 strerror(errno));
1848             }
1849             close(fd);
1850             continue;
1851         }
1852 
1853         result->has_minimum = true;
1854         result->minimum = r.minlen;
1855         result->has_trimmed = true;
1856         result->trimmed = r.len;
1857         close(fd);
1858     }
1859 
1860     free_fs_mount_list(&mounts);
1861     return response;
1862 }
1863 #endif /* CONFIG_FSTRIM */
1864 
1865 
1866 #define LINUX_SYS_STATE_FILE "/sys/power/state"
1867 #define SUSPEND_SUPPORTED 0
1868 #define SUSPEND_NOT_SUPPORTED 1
1869 
1870 typedef enum {
1871     SUSPEND_MODE_DISK = 0,
1872     SUSPEND_MODE_RAM = 1,
1873     SUSPEND_MODE_HYBRID = 2,
1874 } SuspendMode;
1875 
1876 /*
1877  * Executes a command in a child process using g_spawn_sync,
1878  * returning an int >= 0 representing the exit status of the
1879  * process.
1880  *
1881  * If the program wasn't found in path, returns -1.
1882  *
1883  * If a problem happened when creating the child process,
1884  * returns -1 and errp is set.
1885  */
1886 static int run_process_child(const char *command[], Error **errp)
1887 {
1888     int exit_status, spawn_flag;
1889     GError *g_err = NULL;
1890     bool success;
1891 
1892     spawn_flag = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL |
1893                  G_SPAWN_STDERR_TO_DEV_NULL;
1894 
1895     success =  g_spawn_sync(NULL, (char **)command, NULL, spawn_flag,
1896                             NULL, NULL, NULL, NULL,
1897                             &exit_status, &g_err);
1898 
1899     if (success) {
1900         return WEXITSTATUS(exit_status);
1901     }
1902 
1903     if (g_err && (g_err->code != G_SPAWN_ERROR_NOENT)) {
1904         error_setg(errp, "failed to create child process, error '%s'",
1905                    g_err->message);
1906     }
1907 
1908     g_error_free(g_err);
1909     return -1;
1910 }
1911 
1912 static bool systemd_supports_mode(SuspendMode mode, Error **errp)
1913 {
1914     const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend",
1915                                      "systemd-hybrid-sleep"};
1916     const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL};
1917     int status;
1918 
1919     status = run_process_child(cmd, errp);
1920 
1921     /*
1922      * systemctl status uses LSB return codes so we can expect
1923      * status > 0 and be ok. To assert if the guest has support
1924      * for the selected suspend mode, status should be < 4. 4 is
1925      * the code for unknown service status, the return value when
1926      * the service does not exist. A common value is status = 3
1927      * (program is not running).
1928      */
1929     if (status > 0 && status < 4) {
1930         return true;
1931     }
1932 
1933     return false;
1934 }
1935 
1936 static void systemd_suspend(SuspendMode mode, Error **errp)
1937 {
1938     Error *local_err = NULL;
1939     const char *systemctl_args[3] = {"hibernate", "suspend", "hybrid-sleep"};
1940     const char *cmd[3] = {"systemctl", systemctl_args[mode], NULL};
1941     int status;
1942 
1943     status = run_process_child(cmd, &local_err);
1944 
1945     if (status == 0) {
1946         return;
1947     }
1948 
1949     if ((status == -1) && !local_err) {
1950         error_setg(errp, "the helper program 'systemctl %s' was not found",
1951                    systemctl_args[mode]);
1952         return;
1953     }
1954 
1955     if (local_err) {
1956         error_propagate(errp, local_err);
1957     } else {
1958         error_setg(errp, "the helper program 'systemctl %s' returned an "
1959                    "unexpected exit status code (%d)",
1960                    systemctl_args[mode], status);
1961     }
1962 }
1963 
1964 static bool pmutils_supports_mode(SuspendMode mode, Error **errp)
1965 {
1966     Error *local_err = NULL;
1967     const char *pmutils_args[3] = {"--hibernate", "--suspend",
1968                                    "--suspend-hybrid"};
1969     const char *cmd[3] = {"pm-is-supported", pmutils_args[mode], NULL};
1970     int status;
1971 
1972     status = run_process_child(cmd, &local_err);
1973 
1974     if (status == SUSPEND_SUPPORTED) {
1975         return true;
1976     }
1977 
1978     if ((status == -1) && !local_err) {
1979         return false;
1980     }
1981 
1982     if (local_err) {
1983         error_propagate(errp, local_err);
1984     } else {
1985         error_setg(errp,
1986                    "the helper program '%s' returned an unexpected exit"
1987                    " status code (%d)", "pm-is-supported", status);
1988     }
1989 
1990     return false;
1991 }
1992 
1993 static void pmutils_suspend(SuspendMode mode, Error **errp)
1994 {
1995     Error *local_err = NULL;
1996     const char *pmutils_binaries[3] = {"pm-hibernate", "pm-suspend",
1997                                        "pm-suspend-hybrid"};
1998     const char *cmd[2] = {pmutils_binaries[mode], NULL};
1999     int status;
2000 
2001     status = run_process_child(cmd, &local_err);
2002 
2003     if (status == 0) {
2004         return;
2005     }
2006 
2007     if ((status == -1) && !local_err) {
2008         error_setg(errp, "the helper program '%s' was not found",
2009                    pmutils_binaries[mode]);
2010         return;
2011     }
2012 
2013     if (local_err) {
2014         error_propagate(errp, local_err);
2015     } else {
2016         error_setg(errp,
2017                    "the helper program '%s' returned an unexpected exit"
2018                    " status code (%d)", pmutils_binaries[mode], status);
2019     }
2020 }
2021 
2022 static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp)
2023 {
2024     const char *sysfile_strs[3] = {"disk", "mem", NULL};
2025     const char *sysfile_str = sysfile_strs[mode];
2026     char buf[32]; /* hopefully big enough */
2027     int fd;
2028     ssize_t ret;
2029 
2030     if (!sysfile_str) {
2031         error_setg(errp, "unknown guest suspend mode");
2032         return false;
2033     }
2034 
2035     fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
2036     if (fd < 0) {
2037         return false;
2038     }
2039 
2040     ret = read(fd, buf, sizeof(buf) - 1);
2041     close(fd);
2042     if (ret <= 0) {
2043         return false;
2044     }
2045     buf[ret] = '\0';
2046 
2047     if (strstr(buf, sysfile_str)) {
2048         return true;
2049     }
2050     return false;
2051 }
2052 
2053 static void linux_sys_state_suspend(SuspendMode mode, Error **errp)
2054 {
2055     Error *local_err = NULL;
2056     const char *sysfile_strs[3] = {"disk", "mem", NULL};
2057     const char *sysfile_str = sysfile_strs[mode];
2058     pid_t pid;
2059     int status;
2060 
2061     if (!sysfile_str) {
2062         error_setg(errp, "unknown guest suspend mode");
2063         return;
2064     }
2065 
2066     pid = fork();
2067     if (!pid) {
2068         /* child */
2069         int fd;
2070 
2071         setsid();
2072         reopen_fd_to_null(0);
2073         reopen_fd_to_null(1);
2074         reopen_fd_to_null(2);
2075 
2076         fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
2077         if (fd < 0) {
2078             _exit(EXIT_FAILURE);
2079         }
2080 
2081         if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
2082             _exit(EXIT_FAILURE);
2083         }
2084 
2085         _exit(EXIT_SUCCESS);
2086     } else if (pid < 0) {
2087         error_setg_errno(errp, errno, "failed to create child process");
2088         return;
2089     }
2090 
2091     ga_wait_child(pid, &status, &local_err);
2092     if (local_err) {
2093         error_propagate(errp, local_err);
2094         return;
2095     }
2096 
2097     if (WEXITSTATUS(status)) {
2098         error_setg(errp, "child process has failed to suspend");
2099     }
2100 
2101 }
2102 
2103 static void guest_suspend(SuspendMode mode, Error **errp)
2104 {
2105     Error *local_err = NULL;
2106     bool mode_supported = false;
2107 
2108     if (systemd_supports_mode(mode, &local_err)) {
2109         mode_supported = true;
2110         systemd_suspend(mode, &local_err);
2111     }
2112 
2113     if (!local_err) {
2114         return;
2115     }
2116 
2117     error_free(local_err);
2118     local_err = NULL;
2119 
2120     if (pmutils_supports_mode(mode, &local_err)) {
2121         mode_supported = true;
2122         pmutils_suspend(mode, &local_err);
2123     }
2124 
2125     if (!local_err) {
2126         return;
2127     }
2128 
2129     error_free(local_err);
2130     local_err = NULL;
2131 
2132     if (linux_sys_state_supports_mode(mode, &local_err)) {
2133         mode_supported = true;
2134         linux_sys_state_suspend(mode, &local_err);
2135     }
2136 
2137     if (!mode_supported) {
2138         error_free(local_err);
2139         error_setg(errp,
2140                    "the requested suspend mode is not supported by the guest");
2141     } else {
2142         error_propagate(errp, local_err);
2143     }
2144 }
2145 
2146 void qmp_guest_suspend_disk(Error **errp)
2147 {
2148     guest_suspend(SUSPEND_MODE_DISK, errp);
2149 }
2150 
2151 void qmp_guest_suspend_ram(Error **errp)
2152 {
2153     guest_suspend(SUSPEND_MODE_RAM, errp);
2154 }
2155 
2156 void qmp_guest_suspend_hybrid(Error **errp)
2157 {
2158     guest_suspend(SUSPEND_MODE_HYBRID, errp);
2159 }
2160 
2161 /* Transfer online/offline status between @vcpu and the guest system.
2162  *
2163  * On input either @errp or *@errp must be NULL.
2164  *
2165  * In system-to-@vcpu direction, the following @vcpu fields are accessed:
2166  * - R: vcpu->logical_id
2167  * - W: vcpu->online
2168  * - W: vcpu->can_offline
2169  *
2170  * In @vcpu-to-system direction, the following @vcpu fields are accessed:
2171  * - R: vcpu->logical_id
2172  * - R: vcpu->online
2173  *
2174  * Written members remain unmodified on error.
2175  */
2176 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
2177                           char *dirpath, Error **errp)
2178 {
2179     int fd;
2180     int res;
2181     int dirfd;
2182     static const char fn[] = "online";
2183 
2184     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
2185     if (dirfd == -1) {
2186         error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2187         return;
2188     }
2189 
2190     fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
2191     if (fd == -1) {
2192         if (errno != ENOENT) {
2193             error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
2194         } else if (sys2vcpu) {
2195             vcpu->online = true;
2196             vcpu->can_offline = false;
2197         } else if (!vcpu->online) {
2198             error_setg(errp, "logical processor #%" PRId64 " can't be "
2199                        "offlined", vcpu->logical_id);
2200         } /* otherwise pretend successful re-onlining */
2201     } else {
2202         unsigned char status;
2203 
2204         res = pread(fd, &status, 1, 0);
2205         if (res == -1) {
2206             error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
2207         } else if (res == 0) {
2208             error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
2209                        fn);
2210         } else if (sys2vcpu) {
2211             vcpu->online = (status != '0');
2212             vcpu->can_offline = true;
2213         } else if (vcpu->online != (status != '0')) {
2214             status = '0' + vcpu->online;
2215             if (pwrite(fd, &status, 1, 0) == -1) {
2216                 error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
2217                                  fn);
2218             }
2219         } /* otherwise pretend successful re-(on|off)-lining */
2220 
2221         res = close(fd);
2222         g_assert(res == 0);
2223     }
2224 
2225     res = close(dirfd);
2226     g_assert(res == 0);
2227 }
2228 
2229 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
2230 {
2231     GuestLogicalProcessorList *head, **tail;
2232     const char *cpu_dir = "/sys/devices/system/cpu";
2233     const gchar *line;
2234     g_autoptr(GDir) cpu_gdir = NULL;
2235     Error *local_err = NULL;
2236 
2237     head = NULL;
2238     tail = &head;
2239     cpu_gdir = g_dir_open(cpu_dir, 0, NULL);
2240 
2241     if (cpu_gdir == NULL) {
2242         error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir);
2243         return NULL;
2244     }
2245 
2246     while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) {
2247         GuestLogicalProcessor *vcpu;
2248         int64_t id;
2249         if (sscanf(line, "cpu%" PRId64, &id)) {
2250             g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/"
2251                                                     "cpu%" PRId64 "/", id);
2252             vcpu = g_malloc0(sizeof *vcpu);
2253             vcpu->logical_id = id;
2254             vcpu->has_can_offline = true; /* lolspeak ftw */
2255             transfer_vcpu(vcpu, true, path, &local_err);
2256             QAPI_LIST_APPEND(tail, vcpu);
2257         }
2258     }
2259 
2260     if (local_err == NULL) {
2261         /* there's no guest with zero VCPUs */
2262         g_assert(head != NULL);
2263         return head;
2264     }
2265 
2266     qapi_free_GuestLogicalProcessorList(head);
2267     error_propagate(errp, local_err);
2268     return NULL;
2269 }
2270 
2271 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
2272 {
2273     int64_t processed;
2274     Error *local_err = NULL;
2275 
2276     processed = 0;
2277     while (vcpus != NULL) {
2278         char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
2279                                      vcpus->value->logical_id);
2280 
2281         transfer_vcpu(vcpus->value, false, path, &local_err);
2282         g_free(path);
2283         if (local_err != NULL) {
2284             break;
2285         }
2286         ++processed;
2287         vcpus = vcpus->next;
2288     }
2289 
2290     if (local_err != NULL) {
2291         if (processed == 0) {
2292             error_propagate(errp, local_err);
2293         } else {
2294             error_free(local_err);
2295         }
2296     }
2297 
2298     return processed;
2299 }
2300 
2301 void qmp_guest_set_user_password(const char *username,
2302                                  const char *password,
2303                                  bool crypted,
2304                                  Error **errp)
2305 {
2306     Error *local_err = NULL;
2307     char *passwd_path = NULL;
2308     pid_t pid;
2309     int status;
2310     int datafd[2] = { -1, -1 };
2311     char *rawpasswddata = NULL;
2312     size_t rawpasswdlen;
2313     char *chpasswddata = NULL;
2314     size_t chpasswdlen;
2315 
2316     rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp);
2317     if (!rawpasswddata) {
2318         return;
2319     }
2320     rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1);
2321     rawpasswddata[rawpasswdlen] = '\0';
2322 
2323     if (strchr(rawpasswddata, '\n')) {
2324         error_setg(errp, "forbidden characters in raw password");
2325         goto out;
2326     }
2327 
2328     if (strchr(username, '\n') ||
2329         strchr(username, ':')) {
2330         error_setg(errp, "forbidden characters in username");
2331         goto out;
2332     }
2333 
2334     chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata);
2335     chpasswdlen = strlen(chpasswddata);
2336 
2337     passwd_path = g_find_program_in_path("chpasswd");
2338 
2339     if (!passwd_path) {
2340         error_setg(errp, "cannot find 'passwd' program in PATH");
2341         goto out;
2342     }
2343 
2344     if (!g_unix_open_pipe(datafd, FD_CLOEXEC, NULL)) {
2345         error_setg(errp, "cannot create pipe FDs");
2346         goto out;
2347     }
2348 
2349     pid = fork();
2350     if (pid == 0) {
2351         close(datafd[1]);
2352         /* child */
2353         setsid();
2354         dup2(datafd[0], 0);
2355         reopen_fd_to_null(1);
2356         reopen_fd_to_null(2);
2357 
2358         if (crypted) {
2359             execl(passwd_path, "chpasswd", "-e", NULL);
2360         } else {
2361             execl(passwd_path, "chpasswd", NULL);
2362         }
2363         _exit(EXIT_FAILURE);
2364     } else if (pid < 0) {
2365         error_setg_errno(errp, errno, "failed to create child process");
2366         goto out;
2367     }
2368     close(datafd[0]);
2369     datafd[0] = -1;
2370 
2371     if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) {
2372         error_setg_errno(errp, errno, "cannot write new account password");
2373         goto out;
2374     }
2375     close(datafd[1]);
2376     datafd[1] = -1;
2377 
2378     ga_wait_child(pid, &status, &local_err);
2379     if (local_err) {
2380         error_propagate(errp, local_err);
2381         goto out;
2382     }
2383 
2384     if (!WIFEXITED(status)) {
2385         error_setg(errp, "child process has terminated abnormally");
2386         goto out;
2387     }
2388 
2389     if (WEXITSTATUS(status)) {
2390         error_setg(errp, "child process has failed to set user password");
2391         goto out;
2392     }
2393 
2394 out:
2395     g_free(chpasswddata);
2396     g_free(rawpasswddata);
2397     g_free(passwd_path);
2398     if (datafd[0] != -1) {
2399         close(datafd[0]);
2400     }
2401     if (datafd[1] != -1) {
2402         close(datafd[1]);
2403     }
2404 }
2405 
2406 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf,
2407                                int size, Error **errp)
2408 {
2409     int fd;
2410     int res;
2411 
2412     errno = 0;
2413     fd = openat(dirfd, pathname, O_RDONLY);
2414     if (fd == -1) {
2415         error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
2416         return;
2417     }
2418 
2419     res = pread(fd, buf, size, 0);
2420     if (res == -1) {
2421         error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname);
2422     } else if (res == 0) {
2423         error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname);
2424     }
2425     close(fd);
2426 }
2427 
2428 static void ga_write_sysfs_file(int dirfd, const char *pathname,
2429                                 const char *buf, int size, Error **errp)
2430 {
2431     int fd;
2432 
2433     errno = 0;
2434     fd = openat(dirfd, pathname, O_WRONLY);
2435     if (fd == -1) {
2436         error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
2437         return;
2438     }
2439 
2440     if (pwrite(fd, buf, size, 0) == -1) {
2441         error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname);
2442     }
2443 
2444     close(fd);
2445 }
2446 
2447 /* Transfer online/offline status between @mem_blk and the guest system.
2448  *
2449  * On input either @errp or *@errp must be NULL.
2450  *
2451  * In system-to-@mem_blk direction, the following @mem_blk fields are accessed:
2452  * - R: mem_blk->phys_index
2453  * - W: mem_blk->online
2454  * - W: mem_blk->can_offline
2455  *
2456  * In @mem_blk-to-system direction, the following @mem_blk fields are accessed:
2457  * - R: mem_blk->phys_index
2458  * - R: mem_blk->online
2459  *-  R: mem_blk->can_offline
2460  * Written members remain unmodified on error.
2461  */
2462 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk,
2463                                   GuestMemoryBlockResponse *result,
2464                                   Error **errp)
2465 {
2466     char *dirpath;
2467     int dirfd;
2468     char *status;
2469     Error *local_err = NULL;
2470 
2471     if (!sys2memblk) {
2472         DIR *dp;
2473 
2474         if (!result) {
2475             error_setg(errp, "Internal error, 'result' should not be NULL");
2476             return;
2477         }
2478         errno = 0;
2479         dp = opendir("/sys/devices/system/memory/");
2480          /* if there is no 'memory' directory in sysfs,
2481          * we think this VM does not support online/offline memory block,
2482          * any other solution?
2483          */
2484         if (!dp) {
2485             if (errno == ENOENT) {
2486                 result->response =
2487                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
2488             }
2489             goto out1;
2490         }
2491         closedir(dp);
2492     }
2493 
2494     dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/",
2495                               mem_blk->phys_index);
2496     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
2497     if (dirfd == -1) {
2498         if (sys2memblk) {
2499             error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2500         } else {
2501             if (errno == ENOENT) {
2502                 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND;
2503             } else {
2504                 result->response =
2505                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2506             }
2507         }
2508         g_free(dirpath);
2509         goto out1;
2510     }
2511     g_free(dirpath);
2512 
2513     status = g_malloc0(10);
2514     ga_read_sysfs_file(dirfd, "state", status, 10, &local_err);
2515     if (local_err) {
2516         /* treat with sysfs file that not exist in old kernel */
2517         if (errno == ENOENT) {
2518             error_free(local_err);
2519             if (sys2memblk) {
2520                 mem_blk->online = true;
2521                 mem_blk->can_offline = false;
2522             } else if (!mem_blk->online) {
2523                 result->response =
2524                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
2525             }
2526         } else {
2527             if (sys2memblk) {
2528                 error_propagate(errp, local_err);
2529             } else {
2530                 error_free(local_err);
2531                 result->response =
2532                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2533             }
2534         }
2535         goto out2;
2536     }
2537 
2538     if (sys2memblk) {
2539         char removable = '0';
2540 
2541         mem_blk->online = (strncmp(status, "online", 6) == 0);
2542 
2543         ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err);
2544         if (local_err) {
2545             /* if no 'removable' file, it doesn't support offline mem blk */
2546             if (errno == ENOENT) {
2547                 error_free(local_err);
2548                 mem_blk->can_offline = false;
2549             } else {
2550                 error_propagate(errp, local_err);
2551             }
2552         } else {
2553             mem_blk->can_offline = (removable != '0');
2554         }
2555     } else {
2556         if (mem_blk->online != (strncmp(status, "online", 6) == 0)) {
2557             const char *new_state = mem_blk->online ? "online" : "offline";
2558 
2559             ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state),
2560                                 &local_err);
2561             if (local_err) {
2562                 error_free(local_err);
2563                 result->response =
2564                     GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
2565                 goto out2;
2566             }
2567 
2568             result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS;
2569             result->has_error_code = false;
2570         } /* otherwise pretend successful re-(on|off)-lining */
2571     }
2572     g_free(status);
2573     close(dirfd);
2574     return;
2575 
2576 out2:
2577     g_free(status);
2578     close(dirfd);
2579 out1:
2580     if (!sys2memblk) {
2581         result->has_error_code = true;
2582         result->error_code = errno;
2583     }
2584 }
2585 
2586 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
2587 {
2588     GuestMemoryBlockList *head, **tail;
2589     Error *local_err = NULL;
2590     struct dirent *de;
2591     DIR *dp;
2592 
2593     head = NULL;
2594     tail = &head;
2595 
2596     dp = opendir("/sys/devices/system/memory/");
2597     if (!dp) {
2598         /* it's ok if this happens to be a system that doesn't expose
2599          * memory blocks via sysfs, but otherwise we should report
2600          * an error
2601          */
2602         if (errno != ENOENT) {
2603             error_setg_errno(errp, errno, "Can't open directory"
2604                              "\"/sys/devices/system/memory/\"");
2605         }
2606         return NULL;
2607     }
2608 
2609     /* Note: the phys_index of memory block may be discontinuous,
2610      * this is because a memblk is the unit of the Sparse Memory design, which
2611      * allows discontinuous memory ranges (ex. NUMA), so here we should
2612      * traverse the memory block directory.
2613      */
2614     while ((de = readdir(dp)) != NULL) {
2615         GuestMemoryBlock *mem_blk;
2616 
2617         if ((strncmp(de->d_name, "memory", 6) != 0) ||
2618             !(de->d_type & DT_DIR)) {
2619             continue;
2620         }
2621 
2622         mem_blk = g_malloc0(sizeof *mem_blk);
2623         /* The d_name is "memoryXXX",  phys_index is block id, same as XXX */
2624         mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10);
2625         mem_blk->has_can_offline = true; /* lolspeak ftw */
2626         transfer_memory_block(mem_blk, true, NULL, &local_err);
2627         if (local_err) {
2628             break;
2629         }
2630 
2631         QAPI_LIST_APPEND(tail, mem_blk);
2632     }
2633 
2634     closedir(dp);
2635     if (local_err == NULL) {
2636         /* there's no guest with zero memory blocks */
2637         if (head == NULL) {
2638             error_setg(errp, "guest reported zero memory blocks!");
2639         }
2640         return head;
2641     }
2642 
2643     qapi_free_GuestMemoryBlockList(head);
2644     error_propagate(errp, local_err);
2645     return NULL;
2646 }
2647 
2648 GuestMemoryBlockResponseList *
2649 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
2650 {
2651     GuestMemoryBlockResponseList *head, **tail;
2652     Error *local_err = NULL;
2653 
2654     head = NULL;
2655     tail = &head;
2656 
2657     while (mem_blks != NULL) {
2658         GuestMemoryBlockResponse *result;
2659         GuestMemoryBlock *current_mem_blk = mem_blks->value;
2660 
2661         result = g_malloc0(sizeof(*result));
2662         result->phys_index = current_mem_blk->phys_index;
2663         transfer_memory_block(current_mem_blk, false, result, &local_err);
2664         if (local_err) { /* should never happen */
2665             goto err;
2666         }
2667 
2668         QAPI_LIST_APPEND(tail, result);
2669         mem_blks = mem_blks->next;
2670     }
2671 
2672     return head;
2673 err:
2674     qapi_free_GuestMemoryBlockResponseList(head);
2675     error_propagate(errp, local_err);
2676     return NULL;
2677 }
2678 
2679 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
2680 {
2681     Error *local_err = NULL;
2682     char *dirpath;
2683     int dirfd;
2684     char *buf;
2685     GuestMemoryBlockInfo *info;
2686 
2687     dirpath = g_strdup_printf("/sys/devices/system/memory/");
2688     dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
2689     if (dirfd == -1) {
2690         error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2691         g_free(dirpath);
2692         return NULL;
2693     }
2694     g_free(dirpath);
2695 
2696     buf = g_malloc0(20);
2697     ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err);
2698     close(dirfd);
2699     if (local_err) {
2700         g_free(buf);
2701         error_propagate(errp, local_err);
2702         return NULL;
2703     }
2704 
2705     info = g_new0(GuestMemoryBlockInfo, 1);
2706     info->size = strtol(buf, NULL, 16); /* the unit is bytes */
2707 
2708     g_free(buf);
2709 
2710     return info;
2711 }
2712 
2713 #else /* defined(__linux__) */
2714 
2715 void qmp_guest_suspend_disk(Error **errp)
2716 {
2717     error_setg(errp, QERR_UNSUPPORTED);
2718 }
2719 
2720 void qmp_guest_suspend_ram(Error **errp)
2721 {
2722     error_setg(errp, QERR_UNSUPPORTED);
2723 }
2724 
2725 void qmp_guest_suspend_hybrid(Error **errp)
2726 {
2727     error_setg(errp, QERR_UNSUPPORTED);
2728 }
2729 
2730 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
2731 {
2732     error_setg(errp, QERR_UNSUPPORTED);
2733     return NULL;
2734 }
2735 
2736 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
2737 {
2738     error_setg(errp, QERR_UNSUPPORTED);
2739     return -1;
2740 }
2741 
2742 void qmp_guest_set_user_password(const char *username,
2743                                  const char *password,
2744                                  bool crypted,
2745                                  Error **errp)
2746 {
2747     error_setg(errp, QERR_UNSUPPORTED);
2748 }
2749 
2750 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
2751 {
2752     error_setg(errp, QERR_UNSUPPORTED);
2753     return NULL;
2754 }
2755 
2756 GuestMemoryBlockResponseList *
2757 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
2758 {
2759     error_setg(errp, QERR_UNSUPPORTED);
2760     return NULL;
2761 }
2762 
2763 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
2764 {
2765     error_setg(errp, QERR_UNSUPPORTED);
2766     return NULL;
2767 }
2768 
2769 #endif
2770 
2771 #ifdef HAVE_GETIFADDRS
2772 static GuestNetworkInterface *
2773 guest_find_interface(GuestNetworkInterfaceList *head,
2774                      const char *name)
2775 {
2776     for (; head; head = head->next) {
2777         if (strcmp(head->value->name, name) == 0) {
2778             return head->value;
2779         }
2780     }
2781 
2782     return NULL;
2783 }
2784 
2785 static int guest_get_network_stats(const char *name,
2786                        GuestNetworkInterfaceStat *stats)
2787 {
2788 #ifdef CONFIG_LINUX
2789     int name_len;
2790     char const *devinfo = "/proc/net/dev";
2791     FILE *fp;
2792     char *line = NULL, *colon;
2793     size_t n = 0;
2794     fp = fopen(devinfo, "r");
2795     if (!fp) {
2796         g_debug("failed to open network stats %s: %s", devinfo,
2797                 g_strerror(errno));
2798         return -1;
2799     }
2800     name_len = strlen(name);
2801     while (getline(&line, &n, fp) != -1) {
2802         long long dummy;
2803         long long rx_bytes;
2804         long long rx_packets;
2805         long long rx_errs;
2806         long long rx_dropped;
2807         long long tx_bytes;
2808         long long tx_packets;
2809         long long tx_errs;
2810         long long tx_dropped;
2811         char *trim_line;
2812         trim_line = g_strchug(line);
2813         if (trim_line[0] == '\0') {
2814             continue;
2815         }
2816         colon = strchr(trim_line, ':');
2817         if (!colon) {
2818             continue;
2819         }
2820         if (colon - name_len  == trim_line &&
2821            strncmp(trim_line, name, name_len) == 0) {
2822             if (sscanf(colon + 1,
2823                 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
2824                   &rx_bytes, &rx_packets, &rx_errs, &rx_dropped,
2825                   &dummy, &dummy, &dummy, &dummy,
2826                   &tx_bytes, &tx_packets, &tx_errs, &tx_dropped,
2827                   &dummy, &dummy, &dummy, &dummy) != 16) {
2828                 continue;
2829             }
2830             stats->rx_bytes = rx_bytes;
2831             stats->rx_packets = rx_packets;
2832             stats->rx_errs = rx_errs;
2833             stats->rx_dropped = rx_dropped;
2834             stats->tx_bytes = tx_bytes;
2835             stats->tx_packets = tx_packets;
2836             stats->tx_errs = tx_errs;
2837             stats->tx_dropped = tx_dropped;
2838             fclose(fp);
2839             g_free(line);
2840             return 0;
2841         }
2842     }
2843     fclose(fp);
2844     g_free(line);
2845     g_debug("/proc/net/dev: Interface '%s' not found", name);
2846 #else /* !CONFIG_LINUX */
2847     g_debug("Network stats reporting available only for Linux");
2848 #endif /* !CONFIG_LINUX */
2849     return -1;
2850 }
2851 
2852 /*
2853  * Build information about guest interfaces
2854  */
2855 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
2856 {
2857     GuestNetworkInterfaceList *head = NULL, **tail = &head;
2858     struct ifaddrs *ifap, *ifa;
2859 
2860     if (getifaddrs(&ifap) < 0) {
2861         error_setg_errno(errp, errno, "getifaddrs failed");
2862         goto error;
2863     }
2864 
2865     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2866         GuestNetworkInterface *info;
2867         GuestIpAddressList **address_tail;
2868         GuestIpAddress *address_item = NULL;
2869         GuestNetworkInterfaceStat *interface_stat = NULL;
2870         char addr4[INET_ADDRSTRLEN];
2871         char addr6[INET6_ADDRSTRLEN];
2872         int sock;
2873         struct ifreq ifr;
2874         unsigned char *mac_addr;
2875         void *p;
2876 
2877         g_debug("Processing %s interface", ifa->ifa_name);
2878 
2879         info = guest_find_interface(head, ifa->ifa_name);
2880 
2881         if (!info) {
2882             info = g_malloc0(sizeof(*info));
2883             info->name = g_strdup(ifa->ifa_name);
2884 
2885             QAPI_LIST_APPEND(tail, info);
2886         }
2887 
2888         if (!info->has_hardware_address) {
2889             /* we haven't obtained HW address yet */
2890             sock = socket(PF_INET, SOCK_STREAM, 0);
2891             if (sock == -1) {
2892                 error_setg_errno(errp, errno, "failed to create socket");
2893                 goto error;
2894             }
2895 
2896             memset(&ifr, 0, sizeof(ifr));
2897             pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->name);
2898             if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
2899                 /*
2900                  * We can't get the hw addr of this interface, but that's not a
2901                  * fatal error. Don't set info->hardware_address, but keep
2902                  * going.
2903                  */
2904                 if (errno == EADDRNOTAVAIL) {
2905                     /* The interface doesn't have a hw addr (e.g. loopback). */
2906                     g_debug("failed to get MAC address of %s: %s",
2907                             ifa->ifa_name, strerror(errno));
2908                 } else{
2909                     g_warning("failed to get MAC address of %s: %s",
2910                               ifa->ifa_name, strerror(errno));
2911                 }
2912 
2913             } else {
2914 #ifdef CONFIG_SOLARIS
2915                 mac_addr = (unsigned char *) &ifr.ifr_addr.sa_data;
2916 #else
2917                 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
2918 #endif
2919                 info->hardware_address =
2920                     g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
2921                                     (int) mac_addr[0], (int) mac_addr[1],
2922                                     (int) mac_addr[2], (int) mac_addr[3],
2923                                     (int) mac_addr[4], (int) mac_addr[5]);
2924 
2925                 info->has_hardware_address = true;
2926             }
2927             close(sock);
2928         }
2929 
2930         if (ifa->ifa_addr &&
2931             ifa->ifa_addr->sa_family == AF_INET) {
2932             /* interface with IPv4 address */
2933             p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
2934             if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
2935                 error_setg_errno(errp, errno, "inet_ntop failed");
2936                 goto error;
2937             }
2938 
2939             address_item = g_malloc0(sizeof(*address_item));
2940             address_item->ip_address = g_strdup(addr4);
2941             address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
2942 
2943             if (ifa->ifa_netmask) {
2944                 /* Count the number of set bits in netmask.
2945                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
2946                 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
2947                 address_item->prefix = ctpop32(((uint32_t *) p)[0]);
2948             }
2949         } else if (ifa->ifa_addr &&
2950                    ifa->ifa_addr->sa_family == AF_INET6) {
2951             /* interface with IPv6 address */
2952             p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
2953             if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
2954                 error_setg_errno(errp, errno, "inet_ntop failed");
2955                 goto error;
2956             }
2957 
2958             address_item = g_malloc0(sizeof(*address_item));
2959             address_item->ip_address = g_strdup(addr6);
2960             address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
2961 
2962             if (ifa->ifa_netmask) {
2963                 /* Count the number of set bits in netmask.
2964                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
2965                 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
2966                 address_item->prefix =
2967                     ctpop32(((uint32_t *) p)[0]) +
2968                     ctpop32(((uint32_t *) p)[1]) +
2969                     ctpop32(((uint32_t *) p)[2]) +
2970                     ctpop32(((uint32_t *) p)[3]);
2971             }
2972         }
2973 
2974         if (!address_item) {
2975             continue;
2976         }
2977 
2978         address_tail = &info->ip_addresses;
2979         while (*address_tail) {
2980             address_tail = &(*address_tail)->next;
2981         }
2982         QAPI_LIST_APPEND(address_tail, address_item);
2983 
2984         info->has_ip_addresses = true;
2985 
2986         if (!info->has_statistics) {
2987             interface_stat = g_malloc0(sizeof(*interface_stat));
2988             if (guest_get_network_stats(info->name, interface_stat) == -1) {
2989                 info->has_statistics = false;
2990                 g_free(interface_stat);
2991             } else {
2992                 info->statistics = interface_stat;
2993                 info->has_statistics = true;
2994             }
2995         }
2996     }
2997 
2998     freeifaddrs(ifap);
2999     return head;
3000 
3001 error:
3002     freeifaddrs(ifap);
3003     qapi_free_GuestNetworkInterfaceList(head);
3004     return NULL;
3005 }
3006 
3007 #else
3008 
3009 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
3010 {
3011     error_setg(errp, QERR_UNSUPPORTED);
3012     return NULL;
3013 }
3014 
3015 #endif /* HAVE_GETIFADDRS */
3016 
3017 #if !defined(CONFIG_FSFREEZE)
3018 
3019 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
3020 {
3021     error_setg(errp, QERR_UNSUPPORTED);
3022     return NULL;
3023 }
3024 
3025 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
3026 {
3027     error_setg(errp, QERR_UNSUPPORTED);
3028 
3029     return 0;
3030 }
3031 
3032 int64_t qmp_guest_fsfreeze_freeze(Error **errp)
3033 {
3034     error_setg(errp, QERR_UNSUPPORTED);
3035 
3036     return 0;
3037 }
3038 
3039 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
3040                                        strList *mountpoints,
3041                                        Error **errp)
3042 {
3043     error_setg(errp, QERR_UNSUPPORTED);
3044 
3045     return 0;
3046 }
3047 
3048 int64_t qmp_guest_fsfreeze_thaw(Error **errp)
3049 {
3050     error_setg(errp, QERR_UNSUPPORTED);
3051 
3052     return 0;
3053 }
3054 
3055 GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
3056 {
3057     error_setg(errp, QERR_UNSUPPORTED);
3058     return NULL;
3059 }
3060 
3061 #endif /* CONFIG_FSFREEZE */
3062 
3063 #if !defined(CONFIG_FSTRIM)
3064 GuestFilesystemTrimResponse *
3065 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
3066 {
3067     error_setg(errp, QERR_UNSUPPORTED);
3068     return NULL;
3069 }
3070 #endif
3071 
3072 /* add unsupported commands to the blacklist */
3073 GList *ga_command_blacklist_init(GList *blacklist)
3074 {
3075 #if !defined(__linux__)
3076     {
3077         const char *list[] = {
3078             "guest-suspend-disk", "guest-suspend-ram",
3079             "guest-suspend-hybrid", "guest-get-vcpus", "guest-set-vcpus",
3080             "guest-get-memory-blocks", "guest-set-memory-blocks",
3081             "guest-get-memory-block-size", "guest-get-memory-block-info",
3082             NULL};
3083         char **p = (char **)list;
3084 
3085         while (*p) {
3086             blacklist = g_list_append(blacklist, g_strdup(*p++));
3087         }
3088     }
3089 #endif
3090 
3091 #if !defined(HAVE_GETIFADDRS)
3092     blacklist = g_list_append(blacklist,
3093                               g_strdup("guest-network-get-interfaces"));
3094 #endif
3095 
3096 #if !defined(CONFIG_FSFREEZE)
3097     {
3098         const char *list[] = {
3099             "guest-get-fsinfo", "guest-fsfreeze-status",
3100             "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list",
3101             "guest-fsfreeze-thaw", "guest-get-fsinfo",
3102             "guest-get-disks", NULL};
3103         char **p = (char **)list;
3104 
3105         while (*p) {
3106             blacklist = g_list_append(blacklist, g_strdup(*p++));
3107         }
3108     }
3109 #endif
3110 
3111 #if !defined(CONFIG_FSTRIM)
3112     blacklist = g_list_append(blacklist, g_strdup("guest-fstrim"));
3113 #endif
3114 
3115     blacklist = g_list_append(blacklist, g_strdup("guest-get-devices"));
3116 
3117     return blacklist;
3118 }
3119 
3120 /* register init/cleanup routines for stateful command groups */
3121 void ga_command_state_init(GAState *s, GACommandState *cs)
3122 {
3123 #if defined(CONFIG_FSFREEZE)
3124     ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
3125 #endif
3126 }
3127 
3128 #ifdef HAVE_UTMPX
3129 
3130 #define QGA_MICRO_SECOND_TO_SECOND 1000000
3131 
3132 static double ga_get_login_time(struct utmpx *user_info)
3133 {
3134     double seconds = (double)user_info->ut_tv.tv_sec;
3135     double useconds = (double)user_info->ut_tv.tv_usec;
3136     useconds /= QGA_MICRO_SECOND_TO_SECOND;
3137     return seconds + useconds;
3138 }
3139 
3140 GuestUserList *qmp_guest_get_users(Error **errp)
3141 {
3142     GHashTable *cache = NULL;
3143     GuestUserList *head = NULL, **tail = &head;
3144     struct utmpx *user_info = NULL;
3145     gpointer value = NULL;
3146     GuestUser *user = NULL;
3147     double login_time = 0;
3148 
3149     cache = g_hash_table_new(g_str_hash, g_str_equal);
3150     setutxent();
3151 
3152     for (;;) {
3153         user_info = getutxent();
3154         if (user_info == NULL) {
3155             break;
3156         } else if (user_info->ut_type != USER_PROCESS) {
3157             continue;
3158         } else if (g_hash_table_contains(cache, user_info->ut_user)) {
3159             value = g_hash_table_lookup(cache, user_info->ut_user);
3160             user = (GuestUser *)value;
3161             login_time = ga_get_login_time(user_info);
3162             /* We're ensuring the earliest login time to be sent */
3163             if (login_time < user->login_time) {
3164                 user->login_time = login_time;
3165             }
3166             continue;
3167         }
3168 
3169         user = g_new0(GuestUser, 1);
3170         user->user = g_strdup(user_info->ut_user);
3171         user->login_time = ga_get_login_time(user_info);
3172 
3173         g_hash_table_insert(cache, user->user, user);
3174 
3175         QAPI_LIST_APPEND(tail, user);
3176     }
3177     endutxent();
3178     g_hash_table_destroy(cache);
3179     return head;
3180 }
3181 
3182 #else
3183 
3184 GuestUserList *qmp_guest_get_users(Error **errp)
3185 {
3186     error_setg(errp, QERR_UNSUPPORTED);
3187     return NULL;
3188 }
3189 
3190 #endif
3191 
3192 /* Replace escaped special characters with theire real values. The replacement
3193  * is done in place -- returned value is in the original string.
3194  */
3195 static void ga_osrelease_replace_special(gchar *value)
3196 {
3197     gchar *p, *p2, quote;
3198 
3199     /* Trim the string at first space or semicolon if it is not enclosed in
3200      * single or double quotes. */
3201     if ((value[0] != '"') || (value[0] == '\'')) {
3202         p = strchr(value, ' ');
3203         if (p != NULL) {
3204             *p = 0;
3205         }
3206         p = strchr(value, ';');
3207         if (p != NULL) {
3208             *p = 0;
3209         }
3210         return;
3211     }
3212 
3213     quote = value[0];
3214     p2 = value;
3215     p = value + 1;
3216     while (*p != 0) {
3217         if (*p == '\\') {
3218             p++;
3219             switch (*p) {
3220             case '$':
3221             case '\'':
3222             case '"':
3223             case '\\':
3224             case '`':
3225                 break;
3226             default:
3227                 /* Keep literal backslash followed by whatever is there */
3228                 p--;
3229                 break;
3230             }
3231         } else if (*p == quote) {
3232             *p2 = 0;
3233             break;
3234         }
3235         *(p2++) = *(p++);
3236     }
3237 }
3238 
3239 static GKeyFile *ga_parse_osrelease(const char *fname)
3240 {
3241     gchar *content = NULL;
3242     gchar *content2 = NULL;
3243     GError *err = NULL;
3244     GKeyFile *keys = g_key_file_new();
3245     const char *group = "[os-release]\n";
3246 
3247     if (!g_file_get_contents(fname, &content, NULL, &err)) {
3248         slog("failed to read '%s', error: %s", fname, err->message);
3249         goto fail;
3250     }
3251 
3252     if (!g_utf8_validate(content, -1, NULL)) {
3253         slog("file is not utf-8 encoded: %s", fname);
3254         goto fail;
3255     }
3256     content2 = g_strdup_printf("%s%s", group, content);
3257 
3258     if (!g_key_file_load_from_data(keys, content2, -1, G_KEY_FILE_NONE,
3259                                    &err)) {
3260         slog("failed to parse file '%s', error: %s", fname, err->message);
3261         goto fail;
3262     }
3263 
3264     g_free(content);
3265     g_free(content2);
3266     return keys;
3267 
3268 fail:
3269     g_error_free(err);
3270     g_free(content);
3271     g_free(content2);
3272     g_key_file_free(keys);
3273     return NULL;
3274 }
3275 
3276 GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
3277 {
3278     GuestOSInfo *info = NULL;
3279     struct utsname kinfo;
3280     GKeyFile *osrelease = NULL;
3281     const char *qga_os_release = g_getenv("QGA_OS_RELEASE");
3282 
3283     info = g_new0(GuestOSInfo, 1);
3284 
3285     if (uname(&kinfo) != 0) {
3286         error_setg_errno(errp, errno, "uname failed");
3287     } else {
3288         info->has_kernel_version = true;
3289         info->kernel_version = g_strdup(kinfo.version);
3290         info->has_kernel_release = true;
3291         info->kernel_release = g_strdup(kinfo.release);
3292         info->has_machine = true;
3293         info->machine = g_strdup(kinfo.machine);
3294     }
3295 
3296     if (qga_os_release != NULL) {
3297         osrelease = ga_parse_osrelease(qga_os_release);
3298     } else {
3299         osrelease = ga_parse_osrelease("/etc/os-release");
3300         if (osrelease == NULL) {
3301             osrelease = ga_parse_osrelease("/usr/lib/os-release");
3302         }
3303     }
3304 
3305     if (osrelease != NULL) {
3306         char *value;
3307 
3308 #define GET_FIELD(field, osfield) do { \
3309     value = g_key_file_get_value(osrelease, "os-release", osfield, NULL); \
3310     if (value != NULL) { \
3311         ga_osrelease_replace_special(value); \
3312         info->has_ ## field = true; \
3313         info->field = value; \
3314     } \
3315 } while (0)
3316         GET_FIELD(id, "ID");
3317         GET_FIELD(name, "NAME");
3318         GET_FIELD(pretty_name, "PRETTY_NAME");
3319         GET_FIELD(version, "VERSION");
3320         GET_FIELD(version_id, "VERSION_ID");
3321         GET_FIELD(variant, "VARIANT");
3322         GET_FIELD(variant_id, "VARIANT_ID");
3323 #undef GET_FIELD
3324 
3325         g_key_file_free(osrelease);
3326     }
3327 
3328     return info;
3329 }
3330 
3331 GuestDeviceInfoList *qmp_guest_get_devices(Error **errp)
3332 {
3333     error_setg(errp, QERR_UNSUPPORTED);
3334 
3335     return NULL;
3336 }
3337 
3338 #ifndef HOST_NAME_MAX
3339 # ifdef _POSIX_HOST_NAME_MAX
3340 #  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
3341 # else
3342 #  define HOST_NAME_MAX 255
3343 # endif
3344 #endif
3345 
3346 char *qga_get_host_name(Error **errp)
3347 {
3348     long len = -1;
3349     g_autofree char *hostname = NULL;
3350 
3351 #ifdef _SC_HOST_NAME_MAX
3352     len = sysconf(_SC_HOST_NAME_MAX);
3353 #endif /* _SC_HOST_NAME_MAX */
3354 
3355     if (len < 0) {
3356         len = HOST_NAME_MAX;
3357     }
3358 
3359     /* Unfortunately, gethostname() below does not guarantee a
3360      * NULL terminated string. Therefore, allocate one byte more
3361      * to be sure. */
3362     hostname = g_new0(char, len + 1);
3363 
3364     if (gethostname(hostname, len) < 0) {
3365         error_setg_errno(errp, errno,
3366                          "cannot get hostname");
3367         return NULL;
3368     }
3369 
3370     return g_steal_pointer(&hostname);
3371 }
3372