pvs/vgs/lvs commands working now.
[libguestfs.git] / daemon / proto.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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <sys/param.h>          /* defines MIN */
29 #include <rpc/types.h>
30 #include <rpc/xdr.h>
31
32 #include "daemon.h"
33 #include "../src/guestfs_protocol.h"
34
35 /* XXX We should make this configurable from /proc/cmdline so that the
36  * verbose setting of the guestfs_h can be inherited here.
37  */
38 #define DEBUG 0
39
40 /* The message currently being processed. */
41 int proc_nr;
42 int serial;
43
44 /* The daemon communications socket. */
45 static int sock;
46
47 void
48 main_loop (int _sock)
49 {
50   XDR xdr;
51   char *buf;
52   char lenbuf[4];
53   unsigned len;
54   struct guestfs_message_header hdr;
55
56   sock = _sock;
57
58   for (;;) {
59     /* Read the length word. */
60     xread (sock, lenbuf, 4);
61     xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
62     xdr_uint32_t (&xdr, &len);
63     xdr_destroy (&xdr);
64
65     if (len > GUESTFS_MESSAGE_MAX) {
66       fprintf (stderr, "guestfsd: incoming message is too long (%u bytes)\n",
67                len);
68       exit (1);
69     }
70
71     buf = malloc (len);
72     if (!buf) {
73       reply_with_perror ("malloc");
74       continue;
75     }
76
77     xread (sock, buf, len);
78
79 #if DEBUG
80     int i, j;
81
82     for (i = 0; i < len; i += 16) {
83       printf ("%04x: ", i);
84       for (j = i; j < MIN (i+16, len); ++j)
85         printf ("%02x ", (unsigned char) buf[j]);
86       for (; j < i+16; ++j)
87         printf ("   ");
88       printf ("|");
89       for (j = i; j < MIN (i+16, len); ++j)
90         if (isprint (buf[j]))
91           printf ("%c", buf[j]);
92         else
93           printf (".");
94       for (; j < i+16; ++j)
95         printf (" ");
96       printf ("|\n");
97     }
98 #endif
99
100     /* Decode the message header. */
101     xdrmem_create (&xdr, buf, len, XDR_DECODE);
102     if (!xdr_guestfs_message_header (&xdr, &hdr)) {
103       fprintf (stderr, "guestfsd: could not decode message header\n");
104       exit (1);
105     }
106
107     /* Check the version etc. */
108     if (hdr.prog != GUESTFS_PROGRAM) {
109       reply_with_error ("wrong program (%d)", hdr.prog);
110       goto cont;
111     }
112     if (hdr.vers != GUESTFS_PROTOCOL_VERSION) {
113       reply_with_error ("wrong protocol version (%d)", hdr.vers);
114       goto cont;
115     }
116     if (hdr.direction != GUESTFS_DIRECTION_CALL) {
117       reply_with_error ("unexpected message direction (%d)", hdr.direction);
118       goto cont;
119     }
120     if (hdr.status != GUESTFS_STATUS_OK) {
121       reply_with_error ("unexpected message status (%d)", hdr.status);
122       goto cont;
123     }
124
125     /* Now start to process this message. */
126     proc_nr = hdr.proc;
127     serial = hdr.serial;
128     dispatch_incoming_message (&xdr);
129     /* Note that dispatch_incoming_message will also send a reply. */
130
131   cont:
132     xdr_destroy (&xdr);
133     free (buf);
134   }
135 }
136
137 static void send_error (const char *msg);
138
139 void
140 reply_with_error (const char *fs, ...)
141 {
142   char err[GUESTFS_ERROR_LEN];
143   va_list args;
144
145   va_start (args, fs);
146   vsnprintf (err, sizeof err, fs, args);
147   va_end (args);
148
149   send_error (err);
150 }
151
152 void
153 reply_with_perror (const char *fs, ...)
154 {
155   char buf1[GUESTFS_ERROR_LEN];
156   char buf2[GUESTFS_ERROR_LEN];
157   va_list args;
158   int err = errno;
159
160   va_start (args, fs);
161   vsnprintf (buf1, sizeof buf1, fs, args);
162   va_end (args);
163
164   snprintf (buf2, sizeof buf2, "%s: %s", buf1, strerror (err));
165
166   send_error (buf2);
167 }
168
169 static void
170 send_error (const char *msg)
171 {
172   XDR xdr;
173   char buf[GUESTFS_ERROR_LEN + 200];
174   char lenbuf[4];
175   struct guestfs_message_header hdr;
176   struct guestfs_message_error err;
177   unsigned len;
178
179   fprintf (stderr, "guestfsd: error: %s\n", msg);
180
181   xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
182
183   hdr.prog = GUESTFS_PROGRAM;
184   hdr.vers = GUESTFS_PROTOCOL_VERSION;
185   hdr.direction = GUESTFS_DIRECTION_REPLY;
186   hdr.status = GUESTFS_STATUS_ERROR;
187   hdr.proc = proc_nr;
188   hdr.serial = serial;
189
190   if (!xdr_guestfs_message_header (&xdr, &hdr)) {
191     fprintf (stderr, "guestfsd: failed to encode error message header\n");
192     exit (1);
193   }
194
195   err.error = (char *) msg;
196
197   if (!xdr_guestfs_message_error (&xdr, &err)) {
198     fprintf (stderr, "guestfsd: failed to encode error message body\n");
199     exit (1);
200   }
201
202   len = xdr_getpos (&xdr);
203   xdr_destroy (&xdr);
204
205   xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE);
206   xdr_uint32_t (&xdr, &len);
207   xdr_destroy (&xdr);
208
209   xwrite (sock, lenbuf, 4);
210   xwrite (sock, buf, len);
211 }
212
213 void
214 reply (xdrproc_t xdrp, char *ret)
215 {
216   XDR xdr;
217   char buf[GUESTFS_MESSAGE_MAX];
218   char lenbuf[4];
219   struct guestfs_message_header hdr;
220   unsigned len;
221
222   xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
223
224   hdr.prog = GUESTFS_PROGRAM;
225   hdr.vers = GUESTFS_PROTOCOL_VERSION;
226   hdr.direction = GUESTFS_DIRECTION_REPLY;
227   hdr.status = GUESTFS_STATUS_OK;
228   hdr.proc = proc_nr;
229   hdr.serial = serial;
230
231   if (!xdr_guestfs_message_header (&xdr, &hdr)) {
232     fprintf (stderr, "guestfsd: failed to encode reply header\n");
233     exit (1);
234   }
235
236   if (xdrp) {
237     if (!(*xdrp) (&xdr, ret)) {
238       fprintf (stderr, "guestfsd: failed to encode reply body\n");
239       exit (1);
240     }
241   }
242
243   len = xdr_getpos (&xdr);
244   xdr_destroy (&xdr);
245
246   xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE);
247   xdr_uint32_t (&xdr, &len);
248   xdr_destroy (&xdr);
249
250   xwrite (sock, lenbuf, 4);
251   xwrite (sock, buf, len);
252 }