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