add packaging
[platform/upstream/binutils.git] / gdb / gdbserver / hostio.c
1 /* Host file transfer support for gdbserver.
2    Copyright (C) 2007-2014 Free Software Foundation, Inc.
3
4    Contributed by CodeSourcery.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "server.h"
22 #include "gdb/fileio.h"
23 #include "hostio.h"
24
25 #include <fcntl.h>
26 #include <limits.h>
27 #include <unistd.h>
28
29 extern int remote_debug;
30
31 struct fd_list
32 {
33   int fd;
34   struct fd_list *next;
35 };
36
37 static struct fd_list *open_fds;
38
39 static int
40 safe_fromhex (char a, int *nibble)
41 {
42   if (a >= '0' && a <= '9')
43     *nibble = a - '0';
44   else if (a >= 'a' && a <= 'f')
45     *nibble = a - 'a' + 10;
46   else if (a >= 'A' && a <= 'F')
47     *nibble = a - 'A' + 10;
48   else
49     return -1;
50
51   return 0;
52 }
53
54 /* Filenames are hex encoded, so the maximum we can handle is half the
55    packet buffer size.  Cap to PATH_MAX, if it is shorter.  */
56 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1))
57 #  define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1)
58 #else
59 #  define HOSTIO_PATH_MAX PATH_MAX
60 #endif
61
62 static int
63 require_filename (char **pp, char *filename)
64 {
65   int count;
66   char *p;
67
68   p = *pp;
69   count = 0;
70
71   while (*p && *p != ',')
72     {
73       int nib1, nib2;
74
75       /* Don't allow overflow.  */
76       if (count >= HOSTIO_PATH_MAX - 1)
77         return -1;
78
79       if (safe_fromhex (p[0], &nib1)
80           || safe_fromhex (p[1], &nib2))
81         return -1;
82
83       filename[count++] = nib1 * 16 + nib2;
84       p += 2;
85     }
86
87   filename[count] = '\0';
88   *pp = p;
89   return 0;
90 }
91
92 static int
93 require_int (char **pp, int *value)
94 {
95   char *p;
96   int count;
97
98   p = *pp;
99   *value = 0;
100   count = 0;
101
102   while (*p && *p != ',')
103     {
104       int nib;
105
106       /* Don't allow overflow.  */
107       if (count >= 7)
108         return -1;
109
110       if (safe_fromhex (p[0], &nib))
111         return -1;
112       *value = *value * 16 + nib;
113       p++;
114       count++;
115     }
116
117   *pp = p;
118   return 0;
119 }
120
121 static int
122 require_data (char *p, int p_len, char **data, int *data_len)
123 {
124   int input_index, output_index, escaped;
125
126   *data = xmalloc (p_len);
127
128   output_index = 0;
129   escaped = 0;
130   for (input_index = 0; input_index < p_len; input_index++)
131     {
132       char b = p[input_index];
133
134       if (escaped)
135         {
136           (*data)[output_index++] = b ^ 0x20;
137           escaped = 0;
138         }
139       else if (b == '}')
140         escaped = 1;
141       else
142         (*data)[output_index++] = b;
143     }
144
145   if (escaped)
146     {
147       free (*data);
148       return -1;
149     }
150
151   *data_len = output_index;
152   return 0;
153 }
154
155 static int
156 require_comma (char **pp)
157 {
158   if (**pp == ',')
159     {
160       (*pp)++;
161       return 0;
162     }
163   else
164     return -1;
165 }
166
167 static int
168 require_end (char *p)
169 {
170   if (*p == '\0')
171     return 0;
172   else
173     return -1;
174 }
175
176 static int
177 require_valid_fd (int fd)
178 {
179   struct fd_list *fd_ptr;
180
181   for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next)
182     if (fd_ptr->fd == fd)
183       return 0;
184
185   return -1;
186 }
187
188 /* Fill in own_buf with the last hostio error packet, however it
189    suitable for the target.  */
190 static void
191 hostio_error (char *own_buf)
192 {
193   the_target->hostio_last_error (own_buf);
194 }
195
196 static void
197 hostio_packet_error (char *own_buf)
198 {
199   sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
200 }
201
202 static void
203 hostio_reply (char *own_buf, int result)
204 {
205   sprintf (own_buf, "F%x", result);
206 }
207
208 static int
209 hostio_reply_with_data (char *own_buf, char *buffer, int len,
210                         int *new_packet_len)
211 {
212   int input_index, output_index, out_maxlen;
213
214   sprintf (own_buf, "F%x;", len);
215   output_index = strlen (own_buf);
216
217   out_maxlen = PBUFSIZ;
218
219   for (input_index = 0; input_index < len; input_index++)
220     {
221       char b = buffer[input_index];
222
223       if (b == '$' || b == '#' || b == '}' || b == '*')
224         {
225           /* These must be escaped.  */
226           if (output_index + 2 > out_maxlen)
227             break;
228           own_buf[output_index++] = '}';
229           own_buf[output_index++] = b ^ 0x20;
230         }
231       else
232         {
233           if (output_index + 1 > out_maxlen)
234             break;
235           own_buf[output_index++] = b;
236         }
237     }
238
239   *new_packet_len = output_index;
240   return input_index;
241 }
242
243 static int
244 fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
245 {
246   int open_flags = 0;
247
248   if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
249     return -1;
250
251   if (fileio_open_flags & FILEIO_O_CREAT)
252     open_flags |= O_CREAT;
253   if (fileio_open_flags & FILEIO_O_EXCL)
254     open_flags |= O_EXCL;
255   if (fileio_open_flags & FILEIO_O_TRUNC)
256     open_flags |= O_TRUNC;
257   if (fileio_open_flags & FILEIO_O_APPEND)
258     open_flags |= O_APPEND;
259   if (fileio_open_flags & FILEIO_O_RDONLY)
260     open_flags |= O_RDONLY;
261   if (fileio_open_flags & FILEIO_O_WRONLY)
262     open_flags |= O_WRONLY;
263   if (fileio_open_flags & FILEIO_O_RDWR)
264     open_flags |= O_RDWR;
265 /* On systems supporting binary and text mode, always open files in
266    binary mode. */
267 #ifdef O_BINARY
268   open_flags |= O_BINARY;
269 #endif
270
271   *open_flags_p = open_flags;
272   return 0;
273 }
274
275 static void
276 handle_open (char *own_buf)
277 {
278   char filename[HOSTIO_PATH_MAX];
279   char *p;
280   int fileio_flags, mode, flags, fd;
281   struct fd_list *new_fd;
282
283   p = own_buf + strlen ("vFile:open:");
284
285   if (require_filename (&p, filename)
286       || require_comma (&p)
287       || require_int (&p, &fileio_flags)
288       || require_comma (&p)
289       || require_int (&p, &mode)
290       || require_end (p)
291       || fileio_open_flags_to_host (fileio_flags, &flags))
292     {
293       hostio_packet_error (own_buf);
294       return;
295     }
296
297   /* We do not need to convert MODE, since the fileio protocol
298      uses the standard values.  */
299   fd = open (filename, flags, mode);
300
301   if (fd == -1)
302     {
303       hostio_error (own_buf);
304       return;
305     }
306
307   /* Record the new file descriptor.  */
308   new_fd = xmalloc (sizeof (struct fd_list));
309   new_fd->fd = fd;
310   new_fd->next = open_fds;
311   open_fds = new_fd;
312
313   hostio_reply (own_buf, fd);
314 }
315
316 static void
317 handle_pread (char *own_buf, int *new_packet_len)
318 {
319   int fd, ret, len, offset, bytes_sent;
320   char *p, *data;
321
322   p = own_buf + strlen ("vFile:pread:");
323
324   if (require_int (&p, &fd)
325       || require_comma (&p)
326       || require_valid_fd (fd)
327       || require_int (&p, &len)
328       || require_comma (&p)
329       || require_int (&p, &offset)
330       || require_end (p))
331     {
332       hostio_packet_error (own_buf);
333       return;
334     }
335
336   data = xmalloc (len);
337 #ifdef HAVE_PREAD
338   ret = pread (fd, data, len, offset);
339 #else
340   ret = -1;
341 #endif
342   /* If we have no pread or it failed for this file, use lseek/read.  */
343   if (ret == -1)
344     {
345       ret = lseek (fd, offset, SEEK_SET);
346       if (ret != -1)
347         ret = read (fd, data, len);
348     }
349
350   if (ret == -1)
351     {
352       hostio_error (own_buf);
353       free (data);
354       return;
355     }
356
357   bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
358
359   /* If we were using read, and the data did not all fit in the reply,
360      we would have to back up using lseek here.  With pread it does
361      not matter.  But we still have a problem; the return value in the
362      packet might be wrong, so we must fix it.  This time it will
363      definitely fit.  */
364   if (bytes_sent < ret)
365     bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
366                                          new_packet_len);
367
368   free (data);
369 }
370
371 static void
372 handle_pwrite (char *own_buf, int packet_len)
373 {
374   int fd, ret, len, offset;
375   char *p, *data;
376
377   p = own_buf + strlen ("vFile:pwrite:");
378
379   if (require_int (&p, &fd)
380       || require_comma (&p)
381       || require_valid_fd (fd)
382       || require_int (&p, &offset)
383       || require_comma (&p)
384       || require_data (p, packet_len - (p - own_buf), &data, &len))
385     {
386       hostio_packet_error (own_buf);
387       return;
388     }
389
390 #ifdef HAVE_PWRITE
391   ret = pwrite (fd, data, len, offset);
392 #else
393   ret = -1;
394 #endif
395   /* If we have no pwrite or it failed for this file, use lseek/write.  */
396   if (ret == -1)
397     {
398       ret = lseek (fd, offset, SEEK_SET);
399       if (ret != -1)
400         ret = write (fd, data, len);
401     }
402
403   if (ret == -1)
404     {
405       hostio_error (own_buf);
406       free (data);
407       return;
408     }
409
410   hostio_reply (own_buf, ret);
411   free (data);
412 }
413
414 static void
415 handle_close (char *own_buf)
416 {
417   int fd, ret;
418   char *p;
419   struct fd_list **open_fd_p, *old_fd;
420
421   p = own_buf + strlen ("vFile:close:");
422
423   if (require_int (&p, &fd)
424       || require_valid_fd (fd)
425       || require_end (p))
426     {
427       hostio_packet_error (own_buf);
428       return;
429     }
430
431   ret = close (fd);
432
433   if (ret == -1)
434     {
435       hostio_error (own_buf);
436       return;
437     }
438
439   open_fd_p = &open_fds;
440   /* We know that fd is in the list, thanks to require_valid_fd.  */
441   while ((*open_fd_p)->fd != fd)
442     open_fd_p = &(*open_fd_p)->next;
443
444   old_fd = *open_fd_p;
445   *open_fd_p = (*open_fd_p)->next;
446   free (old_fd);
447
448   hostio_reply (own_buf, ret);
449 }
450
451 static void
452 handle_unlink (char *own_buf)
453 {
454   char filename[HOSTIO_PATH_MAX];
455   char *p;
456   int ret;
457
458   p = own_buf + strlen ("vFile:unlink:");
459
460   if (require_filename (&p, filename)
461       || require_end (p))
462     {
463       hostio_packet_error (own_buf);
464       return;
465     }
466
467   ret = unlink (filename);
468
469   if (ret == -1)
470     {
471       hostio_error (own_buf);
472       return;
473     }
474
475   hostio_reply (own_buf, ret);
476 }
477
478 static void
479 handle_readlink (char *own_buf, int *new_packet_len)
480 {
481 #if defined (HAVE_READLINK)
482   char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX];
483   char *p;
484   int ret, bytes_sent;
485
486   p = own_buf + strlen ("vFile:readlink:");
487
488   if (require_filename (&p, filename)
489       || require_end (p))
490     {
491       hostio_packet_error (own_buf);
492       return;
493     }
494
495   ret = readlink (filename, linkname, sizeof (linkname) - 1);
496   if (ret == -1)
497     {
498       hostio_error (own_buf);
499       return;
500     }
501
502   bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
503
504   /* If the response does not fit into a single packet, do not attempt
505      to return a partial response, but simply fail.  */
506   if (bytes_sent < ret)
507     sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG);
508 #else /* ! HAVE_READLINK */
509     sprintf (own_buf, "F-1,%x", FILEIO_ENOSYS);
510 #endif
511 }
512
513 /* Handle all the 'F' file transfer packets.  */
514
515 int
516 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
517 {
518   if (strncmp (own_buf, "vFile:open:", 11) == 0)
519     handle_open (own_buf);
520   else if (strncmp (own_buf, "vFile:pread:", 11) == 0)
521     handle_pread (own_buf, new_packet_len);
522   else if (strncmp (own_buf, "vFile:pwrite:", 12) == 0)
523     handle_pwrite (own_buf, packet_len);
524   else if (strncmp (own_buf, "vFile:close:", 12) == 0)
525     handle_close (own_buf);
526   else if (strncmp (own_buf, "vFile:unlink:", 13) == 0)
527     handle_unlink (own_buf);
528   else if (strncmp (own_buf, "vFile:readlink:", 15) == 0)
529     handle_readlink (own_buf, new_packet_len);
530   else
531     return 0;
532
533   return 1;
534 }