More files to ignore.
[libguestfs.git] / src / guestfs.c
1 /* libguestfs
2  * Copyright (C) 2009 Red Hat Inc. 
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <config.h>
20
21 #define _BSD_SOURCE /* for mkdtemp, usleep */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <time.h>
31
32 #ifdef HAVE_ERRNO_H
33 #include <errno.h>
34 #endif
35
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_SYS_WAIT_H
41 #include <sys/wait.h>
42 #endif
43
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
46 #endif
47
48 #ifdef HAVE_SYS_UN_H
49 #include <sys/un.h>
50 #endif
51
52 #include "guestfs.h"
53
54 static int error (guestfs_h *g, const char *fs, ...);
55 static int perrorf (guestfs_h *g, const char *fs, ...);
56 static void *safe_malloc (guestfs_h *g, int nbytes);
57 static void *safe_realloc (guestfs_h *g, void *ptr, int nbytes);
58 static char *safe_strdup (guestfs_h *g, const char *str);
59
60 #define VMCHANNEL_PORT 6666
61 #define VMCHANNEL_ADDR "10.0.2.4"
62
63 /* GuestFS handle and connection. */
64 struct guestfs_h
65 {
66   /* All these socks/pids are -1 if not connected. */
67   int sock;                     /* Daemon communications socket. */
68   int pid;                      /* Qemu PID. */
69   time_t start_t;               /* The time when we started qemu. */
70   int daemon_up;                /* Received hello message from daemon. */
71
72   char *tmpdir;                 /* Temporary directory containing logfile
73                                  * and socket.  Cleaned up unless there is
74                                  * an error.
75                                  */
76
77   char **cmdline;               /* Qemu command line. */
78   int cmdline_size;
79
80   guestfs_abort_fn abort_fn;
81   int exit_on_error;
82   int verbose;
83 };
84
85 guestfs_h *
86 guestfs_create (void)
87 {
88   guestfs_h *g;
89
90   g = malloc (sizeof (*g));
91   if (!g) return NULL;
92
93   g->sock = -1;
94   g->pid = -1;
95
96   g->start_t = 0;
97   g->daemon_up = 0;
98
99   g->tmpdir = NULL;
100
101   g->abort_fn = abort;          /* Have to set these before safe_malloc. */
102   g->exit_on_error = 0;
103   g->verbose = getenv ("LIBGUESTFS_VERBOSE") != NULL;
104
105   g->cmdline = safe_malloc (g, sizeof (char *) * 1);
106   g->cmdline_size = 1;
107   g->cmdline[0] = NULL;         /* This is chosen by guestfs_launch. */
108
109   return g;
110 }
111
112 void
113 guestfs_free (guestfs_h *g)
114 {
115   int i;
116   char filename[256];
117
118   if (g->pid) guestfs_kill_subprocess (g);
119
120   /* The assumption is that programs calling this have successfully
121    * used qemu, so delete the logfile and socket directory.
122    */
123   if (g->tmpdir) {
124     snprintf (filename, sizeof filename, "%s/sock", g->tmpdir);
125     unlink (filename);
126
127     snprintf (filename, sizeof filename, "%s/qemu.log", g->tmpdir);
128     unlink (filename);
129
130     rmdir (g->tmpdir);
131
132     free (g->tmpdir);
133   }
134
135   for (i = 0; i < g->cmdline_size; ++i)
136     free (g->cmdline[i]);
137   free (g->cmdline);
138
139   free (g);
140 }
141
142 /* Cleanup fds and sockets, assuming the subprocess is dead already. */
143 static void
144 cleanup_fds (guestfs_h *g)
145 {
146   if (g->sock >= 0) close (g->sock);
147   g->sock = -1;
148 }
149
150 /* Wait for subprocess to exit. */
151 static void
152 wait_subprocess (guestfs_h *g)
153 {
154   if (g->pid >= 0) waitpid (g->pid, NULL, 0);
155   g->pid = -1;
156 }
157
158 static int
159 error (guestfs_h *g, const char *fs, ...)
160 {
161   va_list args;
162
163   fprintf (stderr, "libguestfs: ");
164   va_start (args, fs);
165   vfprintf (stderr, fs, args);
166   va_end (args);
167   fputc ('\n', stderr);
168
169   if (g->exit_on_error) {
170     guestfs_kill_subprocess (g);
171     exit (1);
172   }
173   return -1;
174 }
175
176 static int
177 perrorf (guestfs_h *g, const char *fs, ...)
178 {
179   va_list args;
180   char buf[256];
181   int err = errno;
182
183   fprintf (stderr, "libguestfs: ");
184   va_start (args, fs);
185   vfprintf (stderr, fs, args);
186   va_end (args);
187   strerror_r (err, buf, sizeof buf);
188   fprintf (stderr, ": %s\n", buf);
189
190   if (g->exit_on_error) {
191     guestfs_kill_subprocess (g);
192     exit (1);
193   }
194   return -1;
195 }
196
197 static void *
198 safe_malloc (guestfs_h *g, int nbytes)
199 {
200   void *ptr = malloc (nbytes);
201   if (!ptr) g->abort_fn ();
202   return ptr;
203 }
204
205 static void *
206 safe_realloc (guestfs_h *g, void *ptr, int nbytes)
207 {
208   void *p = realloc (ptr, nbytes);
209   if (!p) g->abort_fn ();
210   return p;
211 }
212
213 static char *
214 safe_strdup (guestfs_h *g, const char *str)
215 {
216   char *s = strdup (str);
217   if (!s) g->abort_fn ();
218   return s;
219 }
220
221 void
222 guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_fn a)
223 {
224   g->abort_fn = a;
225 }
226
227 guestfs_abort_fn
228 guestfs_get_out_of_memory_handler (guestfs_h *g)
229 {
230   return g->abort_fn;
231 }
232
233 void
234 guestfs_set_exit_on_error (guestfs_h *g, int e)
235 {
236   g->exit_on_error = e;
237 }
238
239 int
240 guestfs_get_exit_on_error (guestfs_h *g)
241 {
242   return g->exit_on_error;
243 }
244
245 void
246 guestfs_set_verbose (guestfs_h *g, int v)
247 {
248   g->verbose = v;
249 }
250
251 int
252 guestfs_get_verbose (guestfs_h *g)
253 {
254   return g->verbose;
255 }
256
257 /* Add an escaped string to the current command line. */
258 static int
259 add_cmdline (guestfs_h *g, const char *str)
260 {
261   if (g->pid >= 0)
262     return error (g, "command line cannot be altered after qemu subprocess launched");
263
264   g->cmdline_size++;
265   g->cmdline = safe_realloc (g, g->cmdline, sizeof (char *) * g->cmdline_size);
266   g->cmdline[g->cmdline_size-1] = safe_strdup (g, str);
267
268   return 0;
269 }
270
271 int
272 guestfs_config (guestfs_h *g,
273                 const char *qemu_param, const char *qemu_value)
274 {
275   if (qemu_param[0] != '-')
276     return error (g, "guestfs_config: parameter must begin with '-' character");
277
278   /* A bit fascist, but the user will probably break the extra
279    * parameters that we add if they try to set any of these.
280    */
281   if (strcmp (qemu_param, "-kernel") == 0 ||
282       strcmp (qemu_param, "-initrd") == 0 ||
283       strcmp (qemu_param, "-nographic") == 0 ||
284       strcmp (qemu_param, "-serial") == 0 ||
285       strcmp (qemu_param, "-vnc") == 0 ||
286       strcmp (qemu_param, "-full-screen") == 0 ||
287       strcmp (qemu_param, "-std-vga") == 0 ||
288       strcmp (qemu_param, "-vnc") == 0)
289     return error (g, "guestfs_config: parameter '%s' isn't allowed");
290
291   if (add_cmdline (g, qemu_param) != 0) return -1;
292
293   if (qemu_value != NULL) {
294     if (add_cmdline (g, qemu_value) != 0) return -1;
295   }
296
297   return 0;
298 }
299
300 int
301 guestfs_add_drive (guestfs_h *g, const char *filename)
302 {
303   int len = strlen (filename) + 64;
304   char buf[len];
305
306   if (strchr (filename, ',') != NULL)
307     return error (g, "filename cannot contain ',' (comma) character");
308
309   snprintf (buf, len, "file=%s,media=disk", filename);
310
311   return guestfs_config (g, "-drive", buf);
312 }
313
314 int
315 guestfs_add_cdrom (guestfs_h *g, const char *filename)
316 {
317   int len = strlen (filename) + 64;
318   char buf[len];
319
320   if (strchr (filename, ',') != NULL)
321     return error (g, "filename cannot contain ',' (comma) character");
322
323   snprintf (buf, len, "file=%s,if=ide,index=1,media=cdrom", filename);
324
325   return guestfs_config (g, "-drive", buf);
326 }
327
328 int
329 guestfs_launch (guestfs_h *g)
330 {
331   static const char *dir_template = "/tmp/libguestfsXXXXXX";
332   int r, i;
333   /*const char *qemu = QEMU;*/  /* XXX */
334   const char *qemu = "/home/rjones/d/redhat/libguestfs/qemu";
335   const char *kernel = "/boot/vmlinuz-2.6.27.15-170.2.24.fc10.x86_64";
336   const char *initrd = "/tmp/initrd-2.6.27.15-170.2.24.fc10.x86_64.img";
337   char unixsock[256];
338
339   /* XXX Choose which qemu to run. */
340   /* XXX Choose initrd, etc. */
341
342   /* Make the temporary directory containing the logfile and socket. */
343   if (!g->tmpdir) {
344     g->tmpdir = safe_strdup (g, dir_template);
345     if (mkdtemp (g->tmpdir) == NULL)
346       return perrorf (g, "%s: cannot create temporary directory", dir_template);
347
348     snprintf (unixsock, sizeof unixsock, "%s/sock", g->tmpdir);
349   }
350
351   r = fork ();
352   if (r == -1)
353     return perrorf (g, "fork");
354
355   if (r > 0) {                  /* Parent (library). */
356     g->pid = r;
357
358     /* If qemu is going to die during startup, give it a tiny amount
359      * of time to print the error message.
360      */
361     usleep (10000);
362
363     /* Start the clock ... */
364     time (&g->start_t);
365   }
366   else {                        /* Child (qemu). */
367     char vmchannel[256];
368     char logfile[256];
369     char append[256];
370
371     /* Set up the full command line.  Do this in the subprocess so we
372      * don't need to worry about cleaning up.
373      */
374     g->cmdline[0] = (char *) qemu;
375
376     g->cmdline =
377       realloc (g->cmdline, sizeof (char *) * (g->cmdline_size + 16));
378     if (g->cmdline == NULL) {
379       perror ("realloc");
380       _exit (1);
381     }
382
383     /* Construct the -net channel parameter for qemu. */
384     snprintf (vmchannel, sizeof vmchannel,
385               "channel,%d:unix:%s,server,nowait", VMCHANNEL_PORT, unixsock);
386
387     /* Linux kernel command line. */
388     snprintf (append, sizeof append,
389               "console=ttyS0 guestfs=%s:%d", VMCHANNEL_ADDR, VMCHANNEL_PORT);
390
391     /* XXX -m */
392
393     g->cmdline[g->cmdline_size   ] = "-kernel";
394     g->cmdline[g->cmdline_size+ 1] = (char *) kernel;
395     g->cmdline[g->cmdline_size+ 2] = "-initrd";
396     g->cmdline[g->cmdline_size+ 3] = (char *) initrd;
397     g->cmdline[g->cmdline_size+ 4] = "-append";
398     g->cmdline[g->cmdline_size+ 5] = append;
399     g->cmdline[g->cmdline_size+ 6] = "-nographic";
400     g->cmdline[g->cmdline_size+ 7] = "-serial";
401     g->cmdline[g->cmdline_size+ 8] = "stdio";
402     g->cmdline[g->cmdline_size+ 9] = "-net";
403     g->cmdline[g->cmdline_size+10] = vmchannel;
404     g->cmdline[g->cmdline_size+11] = "-net";
405     g->cmdline[g->cmdline_size+12] = "user,vlan=0";
406     g->cmdline[g->cmdline_size+13] = "-net";
407     g->cmdline[g->cmdline_size+14] = "nic,vlan=0";
408     g->cmdline[g->cmdline_size+15] = NULL;
409
410     if (g->verbose) {
411       fprintf (stderr, "Running %s", qemu);
412       for (i = 0; g->cmdline[i]; ++i)
413         fprintf (stderr, " %s", g->cmdline[i]);
414       fprintf (stderr, "\n");
415     }
416
417     /* Set up stdin, stdout.  Messages should go to the logfile. */
418     close (0);
419     close (1);
420     open ("/dev/null", O_RDONLY);
421     snprintf (logfile, sizeof logfile, "%s/qemu.log", g->tmpdir);
422     open (logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
423     /*dup2 (1, 2);*/
424
425     /* Set up a new process group, so we can signal this process
426      * and all subprocesses (eg. if qemu is really a shell script).
427      */
428     setpgid (0, 0);
429
430     execv (qemu, g->cmdline);   /* Run qemu. */
431     perror (qemu);
432     _exit (1);
433   }
434
435   return 0;
436 }
437
438 /* A peculiarity of qemu's vmchannel implementation is that both sides
439  * connect to qemu, ie:
440  *
441  *   libguestfs  --- connect --> qemu <-- connect --- daemon
442  *    (host)                                          (guest)
443  *
444  * This has several implications: (1) qemu creates the Unix socket, so
445  * we have to wait for it to do that.  (2) we have to arrange for the
446  * daemon to send a "hello" message which we also wait for.
447  *
448  * At any time during this, the qemu subprocess might run slowly, die
449  * or hang (it's very prone to just hanging if the BIOS fails for any
450  * reason or if the kernel cannot be found to boot from).
451  *
452  * The only realistic way to handle this is, unfortunately, using
453  * timeouts, also checking if the qemu subprocess is still alive.
454  *
455  * We could do better here by monitoring the Linux kernel log messages
456  * (via the serial console, which is currently just redirected to a
457  * log file) and seeing if the Linux guest is making progress. (XXX)
458  */
459
460 #define QEMU_SOCKET_TIMEOUT 5   /* How long we wait for qemu to make
461                                  * the socket.  This should be very quick.
462                                  */
463 #define DAEMON_TIMEOUT 60       /* How long we wait for guest to boot
464                                  * and start the daemon.  This could take
465                                  * a potentially long time, and is very
466                                  * sensitive to the overall load on the host.
467                                  */
468
469 static int wait_ready (guestfs_h *g);
470
471 int
472 guestfs_wait_ready (guestfs_h *g)
473 {
474   int r;
475
476   /* Launch the subprocess, if there isn't one already. */
477   if (g->pid == -1) {
478     if (guestfs_launch (g) != 0)
479       return -1;
480   }
481
482   for (;;) {
483     r = wait_ready (g);
484     if (r == -1) {              /* Error. */
485       guestfs_kill_subprocess (g);
486       return -1;
487     }
488     else if (r > 0) {           /* Keep waiting. */
489       sleep (1);
490       continue;
491     }
492     else if (r == 0)            /* Daemon is ready. */
493       break;
494   }
495
496   return 0;
497 }
498
499 #define UNIX_PATH_MAX 108
500
501 /* This function is called repeatedly until the qemu subprocess and
502  * daemon is ready.  It returns:
503  *   -1 : error
504  *    0 : done, daemon is ready
505  *   >0 : not ready, keep waiting
506  */
507 static int
508 wait_ready (guestfs_h *g)
509 {
510   int r, i, sock;
511   time_t now;
512   double elapsed;
513   struct sockaddr_un addr;
514   unsigned char m;
515
516   if (g->pid == -1) abort ();   /* Internal state error. */
517
518   /* Check the daemon is still around. */
519   r = waitpid (g->pid, NULL, WNOHANG);
520
521   if (r > 0 || (r == -1 && errno == ECHILD)) {
522     g->pid = -1;
523     return error (g,
524                   "qemu subprocess exited unexpectedly during initialization");
525   }
526
527   time (&now);
528   elapsed = difftime (now, g->start_t);
529
530   if (g->sock == -1) {
531     /* Create the socket. */
532     sock = socket (AF_UNIX, SOCK_STREAM, 0);
533     if (sock == -1)
534       return perrorf (g, "socket");
535
536     addr.sun_family = AF_UNIX;
537     snprintf (addr.sun_path, UNIX_PATH_MAX, "%s/sock", g->tmpdir);
538
539     if (connect (sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
540       if (elapsed <= QEMU_SOCKET_TIMEOUT) {
541         close (sock);
542         return 1;               /* Keep waiting for the socket ... */
543       }
544       perrorf (g, "qemu process hanging before making vmchannel socket");
545       close (sock);
546       return -1;
547     }
548
549     if (fcntl (sock, F_SETFL, O_NONBLOCK) == -1) {
550       perrorf (g, "set socket non-blocking");
551       close (sock);
552       return -1;
553     }
554
555     g->sock = sock;
556   }
557
558   if (!g->daemon_up) {
559     /* Wait for the daemon to say hello. */
560     errno = 0;
561     r = read (g->sock, &m, 1);
562     if (r == 1) {
563       if (m == 0xF5) {
564         g->daemon_up = 1;
565         return 0;
566       } else {
567         error (g, "unexpected message from qemu vmchannel or daemon");
568         return -1;
569       }
570     }
571     if (errno == EAGAIN) {
572       if (elapsed <= DAEMON_TIMEOUT)
573         return 1;               /* Keep waiting for the daemon ... */
574       error (g, "timeout waiting for guest to become ready");
575       return -1;
576     }
577
578     perrorf (g, "read");
579     return -1;
580   }
581
582   return 0;
583 }
584
585 void
586 guestfs_kill_subprocess (guestfs_h *g)
587 {
588   if (g->pid >= 0) {
589     if (g->verbose)
590       fprintf (stderr, "sending SIGTERM to pgid %d\n", g->pid);
591
592     kill (- g->pid, SIGTERM);
593     wait_subprocess (g);
594   }
595
596   cleanup_fds (g);
597 }