e3b8883eb2c2c472fe038f0bd2677234c28ea521
[libguestfs.git] / daemon / guestfsd.c
1 /* libguestfs - the guestfsd daemon
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #define _BSD_SOURCE             /* for daemon(3) */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <rpc/types.h>
28 #include <rpc/xdr.h>
29 #include <getopt.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/select.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <ctype.h>
38 #include <signal.h>
39 #include <printf.h>
40
41 #include "daemon.h"
42
43 static char *read_cmdline (void);
44
45 /* Also in guestfs.c */
46 #define GUESTFWD_ADDR "10.0.2.4"
47 #define GUESTFWD_PORT "6666"
48
49 int verbose = 0;
50
51 static int print_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args);
52 static int print_sysroot_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args);
53 #ifdef HAVE_REGISTER_PRINTF_SPECIFIER
54 static int print_arginfo (const struct printf_info *info, size_t n, int *argtypes, int *size);
55 #else
56 #ifdef HAVE_REGISTER_PRINTF_FUNCTION
57 static int print_arginfo (const struct printf_info *info, size_t n, int *argtypes);
58 #else
59 #error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
60 #endif
61 #endif
62
63 /* Location to mount root device. */
64 const char *sysroot = "/sysroot"; /* No trailing slash. */
65 int sysroot_len = 8;
66
67 static void
68 usage (void)
69 {
70   fprintf (stderr,
71     "guestfsd [-f|--foreground] [-c|--channel vmchannel] [-v|--verbose]\n");
72 }
73
74 int
75 main (int argc, char *argv[])
76 {
77   static const char *options = "fc:v?";
78   static const struct option long_options[] = {
79     { "channel", required_argument, 0, 'c' },
80     { "foreground", 0, 0, 'f' },
81     { "help", 0, 0, '?' },
82     { "verbose", 0, 0, 'v' },
83     { 0, 0, 0, 0 }
84   };
85   int c;
86   int dont_fork = 0;
87   char *cmdline;
88   char *vmchannel = NULL;
89
90 #ifdef HAVE_REGISTER_PRINTF_SPECIFIER
91   /* http://udrepper.livejournal.com/20948.html */
92   register_printf_specifier ('Q', print_shell_quote, print_arginfo);
93   register_printf_specifier ('R', print_sysroot_shell_quote, print_arginfo);
94 #else
95 #ifdef HAVE_REGISTER_PRINTF_FUNCTION
96   register_printf_function ('Q', print_shell_quote, print_arginfo);
97   register_printf_function ('R', print_sysroot_shell_quote, print_arginfo);
98 #else
99 #error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
100 #endif
101 #endif
102
103   for (;;) {
104     c = getopt_long (argc, argv, options, long_options, NULL);
105     if (c == -1) break;
106
107     switch (c) {
108     case 'c':
109       vmchannel = optarg;
110       break;
111
112     case 'f':
113       dont_fork = 1;
114       break;
115
116     case 'v':
117       verbose = 1;
118       break;
119
120     case '?':
121       usage ();
122       exit (0);
123
124     default:
125       fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
126       exit (1);
127     }
128   }
129
130   if (optind < argc) {
131     usage ();
132     exit (1);
133   }
134
135   cmdline = read_cmdline ();
136
137   /* Set the verbose flag. */
138   verbose = verbose ||
139     (cmdline && strstr (cmdline, "guestfs_verbose=1") != NULL);
140   if (verbose)
141     printf ("verbose daemon enabled\n");
142
143   if (verbose) {
144     if (cmdline)
145       printf ("linux commmand line: %s\n", cmdline);
146     else
147       printf ("could not read linux command line\n");
148   }
149
150   /* Make sure SIGPIPE doesn't kill us. */
151   struct sigaction sa;
152   memset (&sa, 0, sizeof sa);
153   sa.sa_handler = SIG_IGN;
154   sa.sa_flags = 0;
155   if (sigaction (SIGPIPE, &sa, NULL) == -1)
156     perror ("sigaction SIGPIPE"); /* but try to continue anyway ... */
157
158   /* Set up a basic environment.  After we are called by /init the
159    * environment is essentially empty.
160    * https://bugzilla.redhat.com/show_bug.cgi?id=502074#c5
161    */
162   setenv ("PATH", "/usr/bin:/bin", 1);
163   setenv ("SHELL", "/bin/sh", 1);
164   setenv ("LC_ALL", "C", 1);
165
166   /* We document that umask defaults to 022 (it should be this anyway). */
167   umask (022);
168
169   /* Get the vmchannel string.
170    *
171    * Sources:
172    *   --channel/-c option on the command line
173    *   guestfs_vmchannel=... from the kernel command line
174    *   guestfs=... from the kernel command line
175    *   built-in default
176    *
177    * At the moment we expect this to contain "tcp:ip:port" but in
178    * future it might contain a device name, eg. "/dev/vcon4" for
179    * virtio-console vmchannel.
180    */
181   if (vmchannel == NULL && cmdline) {
182     char *p;
183     size_t len;
184
185     p = strstr (cmdline, "guestfs_vmchannel=");
186     if (p) {
187       len = strcspn (p + 18, " \t\n");
188       vmchannel = strndup (p + 18, len);
189       if (!vmchannel) {
190         perror ("strndup");
191         exit (1);
192       }
193     }
194
195     /* Old libraries passed guestfs=host:port.  Rewrite it as tcp:host:port. */
196     if (vmchannel == NULL) {
197       /* We will rewrite it part of the "guestfs=" string with
198        *                       "tcp:"       hence p + 4 below.    */
199       p = strstr (cmdline, "guestfs=");
200       if (p) {
201         len = strcspn (p + 4, " \t\n");
202         vmchannel = strndup (p + 4, len);
203         if (!vmchannel) {
204           perror ("strndup");
205           exit (1);
206         }
207         memcpy (vmchannel, "tcp:", 4);
208       }
209     }
210   }
211
212   /* Default vmchannel. */
213   if (vmchannel == NULL) {
214     vmchannel = strdup ("tcp:" GUESTFWD_ADDR ":" GUESTFWD_PORT);
215     if (!vmchannel) {
216       perror ("strdup");
217       exit (1);
218     }
219   }
220
221   if (verbose)
222     printf ("vmchannel: %s\n", vmchannel);
223
224   /* Connect to vmchannel. */
225   int sock = -1;
226
227   if (strncmp (vmchannel, "tcp:", 4) == 0) {
228     /* Resolve the hostname. */
229     struct addrinfo *res, *rr;
230     struct addrinfo hints;
231     int r;
232     char *host, *port;
233
234     host = vmchannel+4;
235     port = strchr (host, ':');
236     if (port) {
237       port[0] = '\0';
238       port++;
239     } else {
240       fprintf (stderr, "vmchannel: expecting \"tcp:<ip>:<port>\": %s\n",
241                vmchannel);
242       exit (1);
243     }
244
245     memset (&hints, 0, sizeof hints);
246     hints.ai_socktype = SOCK_STREAM;
247     hints.ai_flags = AI_ADDRCONFIG;
248     r = getaddrinfo (host, port, &hints, &res);
249     if (r != 0) {
250       fprintf (stderr, "%s:%s: %s\n",
251                host, port, gai_strerror (r));
252       exit (1);
253     }
254
255     /* Connect to the given TCP socket. */
256     for (rr = res; rr != NULL; rr = rr->ai_next) {
257       sock = socket (rr->ai_family, rr->ai_socktype, rr->ai_protocol);
258       if (sock != -1) {
259         if (connect (sock, rr->ai_addr, rr->ai_addrlen) == 0)
260           break;
261         perror ("connect");
262
263         close (sock);
264         sock = -1;
265       }
266     }
267     freeaddrinfo (res);
268   } else {
269     fprintf (stderr,
270              "unknown vmchannel connection type: %s\n"
271              "expecting \"tcp:<ip>:<port>\"\n",
272              vmchannel);
273     exit (1);
274   }
275
276   if (sock == -1) {
277     fprintf (stderr,
278              "\n"
279              "Failed to connect to any vmchannel implementation.\n"
280              "vmchannel: %s\n"
281              "\n"
282              "This is a fatal error and the appliance will now exit.\n"
283              "\n"
284              "Usually this error is caused by either QEMU or the appliance\n"
285              "kernel not supporting the vmchannel method that the\n"
286              "libguestfs library chose to use.  Please run\n"
287              "'libguestfs-test-tool' and provide the complete, unedited\n"
288              "output to the libguestfs developers, either in a bug report\n"
289              "or on the libguestfs redhat com mailing list.\n"
290              "\n",
291              vmchannel);
292     exit (1);
293   }
294
295   /* Send the magic length message which indicates that
296    * userspace is up inside the guest.
297    */
298   char lenbuf[4];
299   XDR xdr;
300   uint32_t len = GUESTFS_LAUNCH_FLAG;
301   xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
302   xdr_uint32_t (&xdr, &len);
303
304   if (xwrite (sock, lenbuf, sizeof lenbuf) == -1)
305     exit (1);
306
307   xdr_destroy (&xdr);
308
309   /* Fork into the background. */
310   if (!dont_fork) {
311     if (daemon (0, 1) == -1) {
312       perror ("daemon");
313       exit (1);
314     }
315   }
316
317   /* Enter the main loop, reading and performing actions. */
318   main_loop (sock);
319
320   exit (0);
321 }
322
323 /* Read /proc/cmdline. */
324 static char *
325 read_cmdline (void)
326 {
327   int fd = open ("/proc/cmdline", O_RDONLY);
328   if (fd == -1) {
329     perror ("/proc/cmdline");
330     return NULL;
331   }
332
333   size_t len = 0;
334   ssize_t n;
335   char buf[256];
336   char *r = NULL;
337
338   for (;;) {
339     n = read (fd, buf, sizeof buf);
340     if (n == -1) {
341       perror ("read");
342       free (r);
343       close (fd);
344       return NULL;
345     }
346     if (n == 0)
347       break;
348     char *newr = realloc (r, len + n + 1); /* + 1 is for terminating NUL */
349     if (newr == NULL) {
350       perror ("realloc");
351       free (r);
352       close (fd);
353       return NULL;
354     }
355     r = newr;
356     memcpy (&r[len], buf, n);
357     len += n;
358   }
359
360   if (r)
361     r[len] = '\0';
362
363   if (close (fd) == -1) {
364     perror ("close");
365     free (r);
366     return NULL;
367   }
368
369   return r;
370 }
371
372 /* Turn "/path" into "/sysroot/path".
373  *
374  * Caller must check for NULL and call reply_with_perror ("malloc")
375  * if it is.  Caller must also free the string.
376  *
377  * See also the custom %R printf formatter which does shell quoting too.
378  */
379 char *
380 sysroot_path (const char *path)
381 {
382   char *r;
383   int len = strlen (path) + sysroot_len + 1;
384
385   r = malloc (len);
386   if (r == NULL)
387     return NULL;
388
389   snprintf (r, len, "%s%s", sysroot, path);
390   return r;
391 }
392
393 int
394 xwrite (int sock, const void *v_buf, size_t len)
395 {
396   int r;
397   const char *buf = v_buf;
398
399   while (len > 0) {
400     r = write (sock, buf, len);
401     if (r == -1) {
402       perror ("write");
403       return -1;
404     }
405     buf += r;
406     len -= r;
407   }
408
409   return 0;
410 }
411
412 int
413 xread (int sock, void *v_buf, size_t len)
414 {
415   int r;
416   char *buf = v_buf;
417
418   while (len > 0) {
419     r = read (sock, buf, len);
420     if (r == -1) {
421       perror ("read");
422       return -1;
423     }
424     if (r == 0) {
425       fprintf (stderr, "read: unexpected end of file on fd %d\n", sock);
426       return -1;
427     }
428     buf += r;
429     len -= r;
430   }
431
432   return 0;
433 }
434
435 int
436 add_string (char ***argv, int *size, int *alloc, const char *str)
437 {
438   char **new_argv;
439   char *new_str;
440
441   if (*size >= *alloc) {
442     *alloc += 64;
443     new_argv = realloc (*argv, *alloc * sizeof (char *));
444     if (new_argv == NULL) {
445       reply_with_perror ("realloc");
446       free_strings (*argv);
447       return -1;
448     }
449     *argv = new_argv;
450   }
451
452   if (str) {
453     new_str = strdup (str);
454     if (new_str == NULL) {
455       reply_with_perror ("strdup");
456       free_strings (*argv);
457     }
458   } else
459     new_str = NULL;
460
461   (*argv)[*size] = new_str;
462
463   (*size)++;
464   return 0;
465 }
466
467 int
468 count_strings (char *const *argv)
469 {
470   int argc;
471
472   for (argc = 0; argv[argc] != NULL; ++argc)
473     ;
474   return argc;
475 }
476
477 static int
478 compare (const void *vp1, const void *vp2)
479 {
480   char * const *p1 = (char * const *) vp1;
481   char * const *p2 = (char * const *) vp2;
482   return strcmp (*p1, *p2);
483 }
484
485 void
486 sort_strings (char **argv, int len)
487 {
488   qsort (argv, len, sizeof (char *), compare);
489 }
490
491 void
492 free_strings (char **argv)
493 {
494   int argc;
495
496   for (argc = 0; argv[argc] != NULL; ++argc)
497     free (argv[argc]);
498   free (argv);
499 }
500
501 void
502 free_stringslen (char **argv, int len)
503 {
504   int i;
505
506   for (i = 0; i < len; ++i)
507     free (argv[i]);
508   free (argv);
509 }
510
511 /* This is a more sane version of 'system(3)' for running external
512  * commands.  It uses fork/execvp, so we don't need to worry about
513  * quoting of parameters, and it allows us to capture any error
514  * messages in a buffer.
515  */
516 int
517 command (char **stdoutput, char **stderror, const char *name, ...)
518 {
519   va_list args;
520   const char **argv;
521   char *s;
522   int i, r;
523
524   /* Collect the command line arguments into an array. */
525   i = 2;
526   argv = malloc (sizeof (char *) * i);
527   if (argv == NULL) {
528     perror ("malloc");
529     return -1;
530   }
531   argv[0] = (char *) name;
532   argv[1] = NULL;
533
534   va_start (args, name);
535
536   while ((s = va_arg (args, char *)) != NULL) {
537     const char **p = realloc (argv, sizeof (char *) * (++i));
538     if (p == NULL) {
539       perror ("realloc");
540       free (argv);
541       va_end (args);
542       return -1;
543     }
544     argv = p;
545     argv[i-2] = s;
546     argv[i-1] = NULL;
547   }
548
549   va_end (args);
550
551   r = commandv (stdoutput, stderror, (char **) argv);
552
553   /* NB: Mustn't free the strings which are on the stack. */
554   free (argv);
555
556   return r;
557 }
558
559 /* Same as 'command', but we allow the status code from the
560  * subcommand to be non-zero, and return that status code.
561  * We still return -1 if there was some other error.
562  */
563 int
564 commandr (char **stdoutput, char **stderror, const char *name, ...)
565 {
566   va_list args;
567   const char **argv;
568   char *s;
569   int i, r;
570
571   /* Collect the command line arguments into an array. */
572   i = 2;
573   argv = malloc (sizeof (char *) * i);
574   if (argv == NULL) {
575     perror ("malloc");
576     return -1;
577   }
578   argv[0] = (char *) name;
579   argv[1] = NULL;
580
581   va_start (args, name);
582
583   while ((s = va_arg (args, char *)) != NULL) {
584     const char **p = realloc (argv, sizeof (char *) * (++i));
585     if (p == NULL) {
586       perror ("realloc");
587       free (argv);
588       va_end (args);
589       return -1;
590     }
591     argv = p;
592     argv[i-2] = s;
593     argv[i-1] = NULL;
594   }
595
596   va_end (args);
597
598   r = commandrv (stdoutput, stderror, argv);
599
600   /* NB: Mustn't free the strings which are on the stack. */
601   free (argv);
602
603   return r;
604 }
605
606 /* Same as 'command', but passing an argv. */
607 int
608 commandv (char **stdoutput, char **stderror, char *const *argv)
609 {
610   int r;
611
612   r = commandrv (stdoutput, stderror, (void *) argv);
613   if (r == 0)
614     return 0;
615   else
616     return -1;
617 }
618
619 int
620 commandrv (char **stdoutput, char **stderror, char const* const *argv)
621 {
622   int so_size = 0, se_size = 0;
623   int so_fd[2], se_fd[2];
624   pid_t pid;
625   int r, quit, i;
626   fd_set rset, rset2;
627   char buf[256];
628   char *p;
629
630   if (stdoutput) *stdoutput = NULL;
631   if (stderror) *stderror = NULL;
632
633   if (verbose) {
634     printf ("%s", argv[0]);
635     for (i = 1; argv[i] != NULL; ++i)
636       printf (" %s", argv[i]);
637     printf ("\n");
638   }
639
640   if (pipe (so_fd) == -1 || pipe (se_fd) == -1) {
641     perror ("pipe");
642     return -1;
643   }
644
645   pid = fork ();
646   if (pid == -1) {
647     perror ("fork");
648     close (so_fd[0]);
649     close (so_fd[1]);
650     close (se_fd[0]);
651     close (se_fd[1]);
652     return -1;
653   }
654
655   if (pid == 0) {               /* Child process. */
656     close (0);
657     close (so_fd[0]);
658     close (se_fd[0]);
659     dup2 (so_fd[1], 1);
660     dup2 (se_fd[1], 2);
661     close (so_fd[1]);
662     close (se_fd[1]);
663
664     execvp (argv[0], (void *) argv);
665     perror (argv[0]);
666     _exit (1);
667   }
668
669   /* Parent process. */
670   close (so_fd[1]);
671   close (se_fd[1]);
672
673   FD_ZERO (&rset);
674   FD_SET (so_fd[0], &rset);
675   FD_SET (se_fd[0], &rset);
676
677   quit = 0;
678   while (quit < 2) {
679     rset2 = rset;
680     r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
681     if (r == -1) {
682       perror ("select");
683     quit:
684       if (stdoutput) free (*stdoutput);
685       if (stderror) free (*stderror);
686       close (so_fd[0]);
687       close (se_fd[0]);
688       waitpid (pid, NULL, 0);
689       return -1;
690     }
691
692     if (FD_ISSET (so_fd[0], &rset2)) { /* something on stdout */
693       r = read (so_fd[0], buf, sizeof buf);
694       if (r == -1) {
695         perror ("read");
696         goto quit;
697       }
698       if (r == 0) { FD_CLR (so_fd[0], &rset); quit++; }
699
700       if (r > 0 && stdoutput) {
701         so_size += r;
702         p = realloc (*stdoutput, so_size);
703         if (p == NULL) {
704           perror ("realloc");
705           goto quit;
706         }
707         *stdoutput = p;
708         memcpy (*stdoutput + so_size - r, buf, r);
709       }
710     }
711
712     if (FD_ISSET (se_fd[0], &rset2)) { /* something on stderr */
713       r = read (se_fd[0], buf, sizeof buf);
714       if (r == -1) {
715         perror ("read");
716         goto quit;
717       }
718       if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; }
719
720       if (r > 0 && stderror) {
721         se_size += r;
722         p = realloc (*stderror, se_size);
723         if (p == NULL) {
724           perror ("realloc");
725           goto quit;
726         }
727         *stderror = p;
728         memcpy (*stderror + se_size - r, buf, r);
729       }
730     }
731   }
732
733   close (so_fd[0]);
734   close (se_fd[0]);
735
736   /* Make sure the output buffers are \0-terminated.  Also remove any
737    * trailing \n characters from the error buffer (not from stdout).
738    */
739   if (stdoutput) {
740     void *q = realloc (*stdoutput, so_size+1);
741     if (q == NULL) {
742       perror ("realloc");
743       free (*stdoutput);
744     }
745     *stdoutput = q;
746     if (*stdoutput)
747       (*stdoutput)[so_size] = '\0';
748   }
749   if (stderror) {
750     void *q = realloc (*stderror, se_size+1);
751     if (q == NULL) {
752       perror ("realloc");
753       free (*stderror);
754     }
755     *stderror = q;
756     if (*stderror) {
757       (*stderror)[se_size] = '\0';
758       se_size--;
759       while (se_size >= 0 && (*stderror)[se_size] == '\n')
760         (*stderror)[se_size--] = '\0';
761     }
762   }
763
764   /* Get the exit status of the command. */
765   if (waitpid (pid, &r, 0) != pid) {
766     perror ("waitpid");
767     return -1;
768   }
769
770   if (WIFEXITED (r)) {
771     return WEXITSTATUS (r);
772   } else
773     return -1;
774 }
775
776 /* Split an output string into a NULL-terminated list of lines.
777  * Typically this is used where we have run an external command
778  * which has printed out a list of things, and we want to return
779  * an actual list.
780  *
781  * The corner cases here are quite tricky.  Note in particular:
782  *
783  *   "" -> []
784  *   "\n" -> [""]
785  *   "a\nb" -> ["a"; "b"]
786  *   "a\nb\n" -> ["a"; "b"]
787  *   "a\nb\n\n" -> ["a"; "b"; ""]
788  *
789  * The original string is written over and destroyed by this
790  * function (which is usually OK because it's the 'out' string
791  * from command()).  You can free the original string, because
792  * add_string() strdups the strings.
793  */
794 char **
795 split_lines (char *str)
796 {
797   char **lines = NULL;
798   int size = 0, alloc = 0;
799   char *p, *pend;
800
801   if (strcmp (str, "") == 0)
802     goto empty_list;
803
804   p = str;
805   while (p) {
806     /* Empty last line? */
807     if (p[0] == '\0')
808       break;
809
810     pend = strchr (p, '\n');
811     if (pend) {
812       *pend = '\0';
813       pend++;
814     }
815
816     if (add_string (&lines, &size, &alloc, p) == -1) {
817       return NULL;
818     }
819
820     p = pend;
821   }
822
823  empty_list:
824   if (add_string (&lines, &size, &alloc, NULL) == -1)
825     return NULL;
826
827   return lines;
828 }
829
830 /* printf helper function so we can use %Q ("quoted") and %R to print
831  * shell-quoted strings.  See HACKING file for more details.
832  */
833 static int
834 print_shell_quote (FILE *stream,
835                    const struct printf_info *info ATTRIBUTE_UNUSED,
836                    const void *const *args)
837 {
838 #define SAFE(c) (isalnum((c)) ||                                        \
839                  (c) == '/' || (c) == '-' || (c) == '_' || (c) == '.')
840   int i, len;
841   const char *str = *((const char **) (args[0]));
842
843   for (i = len = 0; str[i]; ++i) {
844     if (!SAFE(str[i])) {
845       putc ('\\', stream);
846       len ++;
847     }
848     putc (str[i], stream);
849     len ++;
850   }
851
852   return len;
853 }
854
855 static int
856 print_sysroot_shell_quote (FILE *stream,
857                            const struct printf_info *info,
858                            const void *const *args)
859 {
860   fputs (sysroot, stream);
861   return sysroot_len + print_shell_quote (stream, info, args);
862 }
863
864 #ifdef HAVE_REGISTER_PRINTF_SPECIFIER
865 static int
866 print_arginfo (const struct printf_info *info ATTRIBUTE_UNUSED,
867                size_t n, int *argtypes, int *size)
868 {
869   if (n > 0) {
870     argtypes[0] = PA_STRING;
871     size[0] = sizeof (const char *);
872   }
873   return 1;
874 }
875 #else
876 #ifdef HAVE_REGISTER_PRINTF_FUNCTION
877 static int
878 print_arginfo (const struct printf_info *info, size_t n, int *argtypes)
879 {
880   if (n > 0)
881     argtypes[0] = PA_STRING;
882   return 1;
883 }
884 #else
885 #error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
886 #endif
887 #endif
888
889 /* Perform device name translation.  Don't call this directly -
890  * use the RESOLVE_DEVICE macro.
891  *
892  * See guestfs(3) for the algorithm.
893  *
894  * We have to open the device and test for ENXIO, because
895  * the device nodes themselves will exist in the appliance.
896  */
897 int
898 device_name_translation (char *device, const char *func)
899 {
900   int fd;
901
902   fd = open (device, O_RDONLY);
903   if (fd >= 0) {
904     close (fd);
905     return 0;
906   }
907
908   if (errno != ENXIO && errno != ENOENT) {
909   error:
910     reply_with_perror ("%s: %s", func, device);
911     return -1;
912   }
913
914   /* If the name begins with "/dev/sd" then try the alternatives. */
915   if (strncmp (device, "/dev/sd", 7) != 0)
916     goto error;
917
918   device[5] = 'h';              /* /dev/hd (old IDE driver) */
919   fd = open (device, O_RDONLY);
920   if (fd >= 0) {
921     close (fd);
922     return 0;
923   }
924
925   device[5] = 'v';              /* /dev/vd (for virtio devices) */
926   fd = open (device, O_RDONLY);
927   if (fd >= 0) {
928     close (fd);
929     return 0;
930   }
931
932   device[5] = 's';              /* Restore original device name. */
933   goto error;
934 }
935
936 /* LVM and other commands aren't synchronous, especially when udev is
937  * involved.  eg. You can create or remove some device, but the /dev
938  * device node won't appear until some time later.  This means that
939  * you get an error if you run one command followed by another.
940  * Use 'udevadm settle' after certain commands, but don't be too
941  * fussed if it fails.
942  */
943 void
944 udev_settle (void)
945 {
946   command (NULL, NULL, "/sbin/udevadm", "settle", NULL);
947 }