Version 1.10.2.
[libguestfs.git] / examples / inspect_vm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <guestfs.h>
5
6 static int
7 compare_keys_len (const void *p1, const void *p2)
8 {
9   const char *key1 = * (char * const *) p1;
10   const char *key2 = * (char * const *) p2;
11   return strlen (key1) - strlen (key2);
12 }
13
14 static size_t
15 count_strings (char *const *argv)
16 {
17   size_t c;
18
19   for (c = 0; argv[c]; ++c)
20     ;
21   return c;
22 }
23
24 int                                                                            
25 main (int argc, char *argv[])
26 {
27   guestfs_h *g;
28   const char *disk;
29   char **roots, *root, *str, **mountpoints, **lines;
30   size_t i, j;
31
32   if (argc != 2) {
33     fprintf (stderr, "usage: inspect_vm disk.img\n");
34     exit (EXIT_FAILURE);
35   }
36   disk = argv[1];
37
38   g = guestfs_create ();
39   if (g == NULL) {
40     perror ("failed to create libguestfs handle");
41     exit (EXIT_FAILURE);
42   }
43
44   /* Attach the disk image read-only to libguestfs. */
45   if (guestfs_add_drive_opts (g, disk,
46      /* GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", */
47         GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
48         -1) /* this marks end of optional arguments */
49       == -1)
50     exit (EXIT_FAILURE);
51
52   /* Run the libguestfs back-end. */
53   if (guestfs_launch (g) == -1)
54     exit (EXIT_FAILURE);
55
56   /* Ask libguestfs to inspect for operating systems. */
57   roots = guestfs_inspect_os (g);
58   if (roots == NULL)
59     exit (EXIT_FAILURE);
60   if (roots[0] == NULL) {
61     fprintf (stderr, "inspect_vm: no operating systems found\n");
62     exit (EXIT_FAILURE);
63   }
64
65   for (j = 0; roots[j] != NULL; ++j) {
66     root = roots[j];
67
68     printf ("Root device: %s\n", root);
69
70     /* Print basic information about the operating system. */
71     str = guestfs_inspect_get_product_name (g, root);
72     if (str)
73       printf ("  Product name: %s\n", str);
74     free (str);
75
76     printf ("  Version:      %d.%d\n",
77             guestfs_inspect_get_major_version (g, root),
78             guestfs_inspect_get_minor_version (g, root));
79
80     str = guestfs_inspect_get_type (g, root);
81     if (str)
82       printf ("  Type:         %s\n", str);
83     free (str);
84     str = guestfs_inspect_get_distro (g, root);
85     if (str)
86       printf ("  Distro:       %s\n", str);
87     free (str);
88
89     /* Mount up the disks, like guestfish -i.
90      *
91      * Sort keys by length, shortest first, so that we end up
92      * mounting the filesystems in the correct order.
93      */
94     mountpoints = guestfs_inspect_get_mountpoints (g, root);
95     if (mountpoints == NULL)
96       exit (EXIT_FAILURE);
97
98     qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
99            compare_keys_len);
100     for (i = 0; mountpoints[i] != NULL; i += 2) {
101       /* Ignore failures from this call, since bogus entries can
102        * appear in the guest's /etc/fstab.
103        */
104       guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
105       free (mountpoints[i]);
106       free (mountpoints[i+1]);
107     }
108     free (mountpoints);
109
110     /* If /etc/issue.net file exists, print up to 3 lines. */
111     if (guestfs_is_file (g, "/etc/issue.net") > 0) {
112       printf ("--- /etc/issue.net ---\n");
113       lines = guestfs_head_n (g, 3, "/etc/issue.net");
114       if (lines == NULL)
115         exit (EXIT_FAILURE);
116       for (i = 0; lines[i] != NULL; ++i) {
117         printf ("%s\n", lines[i]);
118         free (lines[i]);
119       }
120       free (lines);
121     }
122
123     /* Unmount everything. */
124     if (guestfs_umount_all (g) == -1)
125       exit (EXIT_FAILURE);
126
127     free (root);
128   }
129   free (roots);
130
131   guestfs_close (g);
132
133   exit (EXIT_SUCCESS);
134 }