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