daemon: When running external commands, open stdin as /dev/null
[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 <signal.h>
38 #include <printf.h>
39
40 #include "c-ctype.h"
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     open ("/dev/null", O_RDONLY); /* Set stdin to /dev/null (ignore failure) */
658     close (so_fd[0]);
659     close (se_fd[0]);
660     dup2 (so_fd[1], 1);
661     dup2 (se_fd[1], 2);
662     close (so_fd[1]);
663     close (se_fd[1]);
664
665     execvp (argv[0], (void *) argv);
666     perror (argv[0]);
667     _exit (1);
668   }
669
670   /* Parent process. */
671   close (so_fd[1]);
672   close (se_fd[1]);
673
674   FD_ZERO (&rset);
675   FD_SET (so_fd[0], &rset);
676   FD_SET (se_fd[0], &rset);
677
678   quit = 0;
679   while (quit < 2) {
680     rset2 = rset;
681     r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
682     if (r == -1) {
683       perror ("select");
684     quit:
685       if (stdoutput) free (*stdoutput);
686       if (stderror) free (*stderror);
687       close (so_fd[0]);
688       close (se_fd[0]);
689       waitpid (pid, NULL, 0);
690       return -1;
691     }
692
693     if (FD_ISSET (so_fd[0], &rset2)) { /* something on stdout */
694       r = read (so_fd[0], buf, sizeof buf);
695       if (r == -1) {
696         perror ("read");
697         goto quit;
698       }
699       if (r == 0) { FD_CLR (so_fd[0], &rset); quit++; }
700
701       if (r > 0 && stdoutput) {
702         so_size += r;
703         p = realloc (*stdoutput, so_size);
704         if (p == NULL) {
705           perror ("realloc");
706           goto quit;
707         }
708         *stdoutput = p;
709         memcpy (*stdoutput + so_size - r, buf, r);
710       }
711     }
712
713     if (FD_ISSET (se_fd[0], &rset2)) { /* something on stderr */
714       r = read (se_fd[0], buf, sizeof buf);
715       if (r == -1) {
716         perror ("read");
717         goto quit;
718       }
719       if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; }
720
721       if (r > 0 && stderror) {
722         se_size += r;
723         p = realloc (*stderror, se_size);
724         if (p == NULL) {
725           perror ("realloc");
726           goto quit;
727         }
728         *stderror = p;
729         memcpy (*stderror + se_size - r, buf, r);
730       }
731     }
732   }
733
734   close (so_fd[0]);
735   close (se_fd[0]);
736
737   /* Make sure the output buffers are \0-terminated.  Also remove any
738    * trailing \n characters from the error buffer (not from stdout).
739    */
740   if (stdoutput) {
741     void *q = realloc (*stdoutput, so_size+1);
742     if (q == NULL) {
743       perror ("realloc");
744       free (*stdoutput);
745     }
746     *stdoutput = q;
747     if (*stdoutput)
748       (*stdoutput)[so_size] = '\0';
749   }
750   if (stderror) {
751     void *q = realloc (*stderror, se_size+1);
752     if (q == NULL) {
753       perror ("realloc");
754       free (*stderror);
755     }
756     *stderror = q;
757     if (*stderror) {
758       (*stderror)[se_size] = '\0';
759       se_size--;
760       while (se_size >= 0 && (*stderror)[se_size] == '\n')
761         (*stderror)[se_size--] = '\0';
762     }
763   }
764
765   /* Get the exit status of the command. */
766   if (waitpid (pid, &r, 0) != pid) {
767     perror ("waitpid");
768     return -1;
769   }
770
771   if (WIFEXITED (r)) {
772     return WEXITSTATUS (r);
773   } else
774     return -1;
775 }
776
777 /* Split an output string into a NULL-terminated list of lines.
778  * Typically this is used where we have run an external command
779  * which has printed out a list of things, and we want to return
780  * an actual list.
781  *
782  * The corner cases here are quite tricky.  Note in particular:
783  *
784  *   "" -> []
785  *   "\n" -> [""]
786  *   "a\nb" -> ["a"; "b"]
787  *   "a\nb\n" -> ["a"; "b"]
788  *   "a\nb\n\n" -> ["a"; "b"; ""]
789  *
790  * The original string is written over and destroyed by this
791  * function (which is usually OK because it's the 'out' string
792  * from command()).  You can free the original string, because
793  * add_string() strdups the strings.
794  */
795 char **
796 split_lines (char *str)
797 {
798   char **lines = NULL;
799   int size = 0, alloc = 0;
800   char *p, *pend;
801
802   if (strcmp (str, "") == 0)
803     goto empty_list;
804
805   p = str;
806   while (p) {
807     /* Empty last line? */
808     if (p[0] == '\0')
809       break;
810
811     pend = strchr (p, '\n');
812     if (pend) {
813       *pend = '\0';
814       pend++;
815     }
816
817     if (add_string (&lines, &size, &alloc, p) == -1) {
818       return NULL;
819     }
820
821     p = pend;
822   }
823
824  empty_list:
825   if (add_string (&lines, &size, &alloc, NULL) == -1)
826     return NULL;
827
828   return lines;
829 }
830
831 /* printf helper function so we can use %Q ("quoted") and %R to print
832  * shell-quoted strings.  See HACKING file for more details.
833  */
834 static int
835 print_shell_quote (FILE *stream,
836                    const struct printf_info *info ATTRIBUTE_UNUSED,
837                    const void *const *args)
838 {
839 #define SAFE(c) (c_isalnum((c)) ||                                      \
840                  (c) == '/' || (c) == '-' || (c) == '_' || (c) == '.')
841   int i, len;
842   const char *str = *((const char **) (args[0]));
843
844   for (i = len = 0; str[i]; ++i) {
845     if (!SAFE(str[i])) {
846       putc ('\\', stream);
847       len ++;
848     }
849     putc (str[i], stream);
850     len ++;
851   }
852
853   return len;
854 }
855
856 static int
857 print_sysroot_shell_quote (FILE *stream,
858                            const struct printf_info *info,
859                            const void *const *args)
860 {
861   fputs (sysroot, stream);
862   return sysroot_len + print_shell_quote (stream, info, args);
863 }
864
865 #ifdef HAVE_REGISTER_PRINTF_SPECIFIER
866 static int
867 print_arginfo (const struct printf_info *info ATTRIBUTE_UNUSED,
868                size_t n, int *argtypes, int *size)
869 {
870   if (n > 0) {
871     argtypes[0] = PA_STRING;
872     size[0] = sizeof (const char *);
873   }
874   return 1;
875 }
876 #else
877 #ifdef HAVE_REGISTER_PRINTF_FUNCTION
878 static int
879 print_arginfo (const struct printf_info *info, size_t n, int *argtypes)
880 {
881   if (n > 0)
882     argtypes[0] = PA_STRING;
883   return 1;
884 }
885 #else
886 #error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
887 #endif
888 #endif
889
890 /* Perform device name translation.  Don't call this directly -
891  * use the RESOLVE_DEVICE macro.
892  *
893  * See guestfs(3) for the algorithm.
894  *
895  * We have to open the device and test for ENXIO, because
896  * the device nodes themselves will exist in the appliance.
897  */
898 int
899 device_name_translation (char *device, const char *func)
900 {
901   int fd;
902
903   fd = open (device, O_RDONLY);
904   if (fd >= 0) {
905     close (fd);
906     return 0;
907   }
908
909   if (errno != ENXIO && errno != ENOENT) {
910   error:
911     reply_with_perror ("%s: %s", func, device);
912     return -1;
913   }
914
915   /* If the name begins with "/dev/sd" then try the alternatives. */
916   if (strncmp (device, "/dev/sd", 7) != 0)
917     goto error;
918
919   device[5] = 'h';              /* /dev/hd (old IDE driver) */
920   fd = open (device, O_RDONLY);
921   if (fd >= 0) {
922     close (fd);
923     return 0;
924   }
925
926   device[5] = 'v';              /* /dev/vd (for virtio devices) */
927   fd = open (device, O_RDONLY);
928   if (fd >= 0) {
929     close (fd);
930     return 0;
931   }
932
933   device[5] = 's';              /* Restore original device name. */
934   goto error;
935 }
936
937 /* LVM and other commands aren't synchronous, especially when udev is
938  * involved.  eg. You can create or remove some device, but the /dev
939  * device node won't appear until some time later.  This means that
940  * you get an error if you run one command followed by another.
941  * Use 'udevadm settle' after certain commands, but don't be too
942  * fussed if it fails.
943  */
944 void
945 udev_settle (void)
946 {
947   command (NULL, NULL, "/sbin/udevadm", "settle", NULL);
948 }