daemon: debug segv correct use of dereferencing NULL.
[libguestfs.git] / examples / create_disk.c
1 /* Example showing how to create a disk image. */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <guestfs.h>
9
10 int                                                                            
11 main (int argc, char *argv[])
12 {
13   guestfs_h *g;
14   size_t i;
15
16   g = guestfs_create ();
17   if (g == NULL) {
18     perror ("failed to create libguestfs handle");
19     exit (EXIT_FAILURE);
20  }
21
22   /* Create a raw-format sparse disk image, 512 MB in size. */
23   int fd = open ("disk.img", O_CREAT|O_WRONLY|O_TRUNC|O_NOCTTY, 0666);
24   if (fd == -1) {
25     perror ("disk.img");
26     exit (EXIT_FAILURE);
27   }
28   if (ftruncate (fd, 512 * 1024 * 1024) == -1) {
29     perror ("disk.img: truncate");
30     exit (EXIT_FAILURE);
31   }
32   if (close (fd) == -1) {
33     perror ("disk.img: close");
34     exit (EXIT_FAILURE);
35   }
36
37   /* Set the trace flag so that we can see each libguestfs call. */
38   guestfs_set_trace (g, 1);
39
40   /* Set the autosync flag so that the disk will be synchronized
41    * automatically when the libguestfs handle is closed.
42    */
43   guestfs_set_autosync (g, 1);
44
45   /* Add the disk image to libguestfs. */
46   if (guestfs_add_drive_opts (g, "disk.img",
47         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", /* raw format */
48         GUESTFS_ADD_DRIVE_OPTS_READONLY, 0, /* for write */
49         -1) /* this marks end of optional arguments */
50       == -1)
51     exit (EXIT_FAILURE);
52
53   /* Run the libguestfs back-end. */
54   if (guestfs_launch (g) == -1)
55     exit (EXIT_FAILURE);
56
57   /* Get the list of devices.  Because we only added one drive
58    * above, we expect that this list should contain a single
59    * element.
60    */
61   char **devices = guestfs_list_devices (g);
62   if (devices == NULL)
63     exit (EXIT_FAILURE);
64   if (devices[0] == NULL || devices[1] != NULL) {
65     fprintf (stderr, "error: expected a single device from list-devices\n");
66     exit (EXIT_FAILURE);
67   }
68
69   /* Partition the disk as one single MBR partition. */
70   if (guestfs_part_disk (g, devices[0], "mbr") == -1)
71     exit (EXIT_FAILURE);
72
73   /* Get the list of partitions.  We expect a single element, which
74    * is the partition we have just created.
75    */
76   char **partitions = guestfs_list_partitions (g);
77   if (partitions == NULL)
78     exit (EXIT_FAILURE);
79   if (partitions[0] == NULL || partitions[1] != NULL) {
80     fprintf (stderr, "error: expected a single partition from list-partitions\n");
81     exit (EXIT_FAILURE);
82   }
83
84   /* Create a filesystem on the partition. */
85   if (guestfs_mkfs (g, "ext4", partitions[0]) == -1)
86     exit (EXIT_FAILURE);
87
88   /* Now mount the filesystem so that we can add files. */
89   if (guestfs_mount_options (g, "", partitions[0], "/") == -1)
90     exit (EXIT_FAILURE);
91
92   /* Create some files and directories. */
93   if (guestfs_touch (g, "/empty") == -1)
94     exit (EXIT_FAILURE);
95   const char *message = "Hello, world\n";
96   if (guestfs_write (g, "/hello", message, strlen (message)) == -1)
97     exit (EXIT_FAILURE);
98   if (guestfs_mkdir (g, "/foo") == -1)
99     exit (EXIT_FAILURE);
100
101   /* This one uploads the local file /etc/resolv.conf into
102    * the disk image.
103    */
104   if (guestfs_upload (g, "/etc/resolv.conf", "/foo/resolv.conf") == -1)
105     exit (EXIT_FAILURE);
106
107   /* Because 'autosync' was set (above) we can just close the handle
108    * and the disk contents will be synchronized.  You can also do
109    * this manually by calling guestfs_umount_all and guestfs_sync.
110    */
111   guestfs_close (g);
112
113   /* Free up the lists. */
114   for (i = 0; devices[i] != NULL; ++i)
115     free (devices[i]);
116   free (devices);
117   for (i = 0; partitions[i] != NULL; ++i)
118     free (partitions[i]);
119   free (partitions);
120
121   exit (EXIT_SUCCESS);
122 }