Don't assume File-I/O mode bits match the host's format
[deliverable/binutils-gdb.git] / gdb / gdbserver / hostio.c
1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2015 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 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include "fileio.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 /* Filenames are hex encoded, so the maximum we can handle is half the
58 packet buffer size. Cap to PATH_MAX, if it is shorter. */
59 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1))
60 # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1)
61 #else
62 # define HOSTIO_PATH_MAX PATH_MAX
63 #endif
64
65 static int
66 require_filename (char **pp, char *filename)
67 {
68 int count;
69 char *p;
70
71 p = *pp;
72 count = 0;
73
74 while (*p && *p != ',')
75 {
76 int nib1, nib2;
77
78 /* Don't allow overflow. */
79 if (count >= HOSTIO_PATH_MAX - 1)
80 return -1;
81
82 if (safe_fromhex (p[0], &nib1)
83 || safe_fromhex (p[1], &nib2))
84 return -1;
85
86 filename[count++] = nib1 * 16 + nib2;
87 p += 2;
88 }
89
90 filename[count] = '\0';
91 *pp = p;
92 return 0;
93 }
94
95 static int
96 require_int (char **pp, int *value)
97 {
98 char *p;
99 int count;
100
101 p = *pp;
102 *value = 0;
103 count = 0;
104
105 while (*p && *p != ',')
106 {
107 int nib;
108
109 /* Don't allow overflow. */
110 if (count >= 7)
111 return -1;
112
113 if (safe_fromhex (p[0], &nib))
114 return -1;
115 *value = *value * 16 + nib;
116 p++;
117 count++;
118 }
119
120 *pp = p;
121 return 0;
122 }
123
124 static int
125 require_data (char *p, int p_len, char **data, int *data_len)
126 {
127 int input_index, output_index, escaped;
128
129 *data = xmalloc (p_len);
130
131 output_index = 0;
132 escaped = 0;
133 for (input_index = 0; input_index < p_len; input_index++)
134 {
135 char b = p[input_index];
136
137 if (escaped)
138 {
139 (*data)[output_index++] = b ^ 0x20;
140 escaped = 0;
141 }
142 else if (b == '}')
143 escaped = 1;
144 else
145 (*data)[output_index++] = b;
146 }
147
148 if (escaped)
149 {
150 free (*data);
151 return -1;
152 }
153
154 *data_len = output_index;
155 return 0;
156 }
157
158 static int
159 require_comma (char **pp)
160 {
161 if (**pp == ',')
162 {
163 (*pp)++;
164 return 0;
165 }
166 else
167 return -1;
168 }
169
170 static int
171 require_end (char *p)
172 {
173 if (*p == '\0')
174 return 0;
175 else
176 return -1;
177 }
178
179 static int
180 require_valid_fd (int fd)
181 {
182 struct fd_list *fd_ptr;
183
184 for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next)
185 if (fd_ptr->fd == fd)
186 return 0;
187
188 return -1;
189 }
190
191 /* Fill in own_buf with the last hostio error packet, however it
192 suitable for the target. */
193 static void
194 hostio_error (char *own_buf)
195 {
196 the_target->hostio_last_error (own_buf);
197 }
198
199 static void
200 hostio_packet_error (char *own_buf)
201 {
202 sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
203 }
204
205 static void
206 hostio_reply (char *own_buf, int result)
207 {
208 sprintf (own_buf, "F%x", result);
209 }
210
211 static int
212 hostio_reply_with_data (char *own_buf, char *buffer, int len,
213 int *new_packet_len)
214 {
215 int input_index, output_index, out_maxlen;
216
217 sprintf (own_buf, "F%x;", len);
218 output_index = strlen (own_buf);
219
220 out_maxlen = PBUFSIZ;
221
222 for (input_index = 0; input_index < len; input_index++)
223 {
224 char b = buffer[input_index];
225
226 if (b == '$' || b == '#' || b == '}' || b == '*')
227 {
228 /* These must be escaped. */
229 if (output_index + 2 > out_maxlen)
230 break;
231 own_buf[output_index++] = '}';
232 own_buf[output_index++] = b ^ 0x20;
233 }
234 else
235 {
236 if (output_index + 1 > out_maxlen)
237 break;
238 own_buf[output_index++] = b;
239 }
240 }
241
242 *new_packet_len = output_index;
243 return input_index;
244 }
245
246 static void
247 handle_open (char *own_buf)
248 {
249 char filename[HOSTIO_PATH_MAX];
250 char *p;
251 int fileio_flags, fileio_mode, flags, fd;
252 mode_t mode;
253 struct fd_list *new_fd;
254
255 p = own_buf + strlen ("vFile:open:");
256
257 if (require_filename (&p, filename)
258 || require_comma (&p)
259 || require_int (&p, &fileio_flags)
260 || require_comma (&p)
261 || require_int (&p, &fileio_mode)
262 || require_end (p)
263 || fileio_to_host_openflags (fileio_flags, &flags)
264 || fileio_to_host_mode (fileio_mode, &mode))
265 {
266 hostio_packet_error (own_buf);
267 return;
268 }
269
270 /* We do not need to convert MODE, since the fileio protocol
271 uses the standard values. */
272 fd = open (filename, flags, mode);
273
274 if (fd == -1)
275 {
276 hostio_error (own_buf);
277 return;
278 }
279
280 /* Record the new file descriptor. */
281 new_fd = xmalloc (sizeof (struct fd_list));
282 new_fd->fd = fd;
283 new_fd->next = open_fds;
284 open_fds = new_fd;
285
286 hostio_reply (own_buf, fd);
287 }
288
289 static void
290 handle_pread (char *own_buf, int *new_packet_len)
291 {
292 int fd, ret, len, offset, bytes_sent;
293 char *p, *data;
294
295 p = own_buf + strlen ("vFile:pread:");
296
297 if (require_int (&p, &fd)
298 || require_comma (&p)
299 || require_valid_fd (fd)
300 || require_int (&p, &len)
301 || require_comma (&p)
302 || require_int (&p, &offset)
303 || require_end (p))
304 {
305 hostio_packet_error (own_buf);
306 return;
307 }
308
309 data = xmalloc (len);
310 #ifdef HAVE_PREAD
311 ret = pread (fd, data, len, offset);
312 #else
313 ret = -1;
314 #endif
315 /* If we have no pread or it failed for this file, use lseek/read. */
316 if (ret == -1)
317 {
318 ret = lseek (fd, offset, SEEK_SET);
319 if (ret != -1)
320 ret = read (fd, data, len);
321 }
322
323 if (ret == -1)
324 {
325 hostio_error (own_buf);
326 free (data);
327 return;
328 }
329
330 bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
331
332 /* If we were using read, and the data did not all fit in the reply,
333 we would have to back up using lseek here. With pread it does
334 not matter. But we still have a problem; the return value in the
335 packet might be wrong, so we must fix it. This time it will
336 definitely fit. */
337 if (bytes_sent < ret)
338 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
339 new_packet_len);
340
341 free (data);
342 }
343
344 static void
345 handle_pwrite (char *own_buf, int packet_len)
346 {
347 int fd, ret, len, offset;
348 char *p, *data;
349
350 p = own_buf + strlen ("vFile:pwrite:");
351
352 if (require_int (&p, &fd)
353 || require_comma (&p)
354 || require_valid_fd (fd)
355 || require_int (&p, &offset)
356 || require_comma (&p)
357 || require_data (p, packet_len - (p - own_buf), &data, &len))
358 {
359 hostio_packet_error (own_buf);
360 return;
361 }
362
363 #ifdef HAVE_PWRITE
364 ret = pwrite (fd, data, len, offset);
365 #else
366 ret = -1;
367 #endif
368 /* If we have no pwrite or it failed for this file, use lseek/write. */
369 if (ret == -1)
370 {
371 ret = lseek (fd, offset, SEEK_SET);
372 if (ret != -1)
373 ret = write (fd, data, len);
374 }
375
376 if (ret == -1)
377 {
378 hostio_error (own_buf);
379 free (data);
380 return;
381 }
382
383 hostio_reply (own_buf, ret);
384 free (data);
385 }
386
387 static void
388 handle_fstat (char *own_buf, int *new_packet_len)
389 {
390 int fd, bytes_sent;
391 char *p;
392 struct stat st;
393 struct fio_stat fst;
394
395 p = own_buf + strlen ("vFile:fstat:");
396
397 if (require_int (&p, &fd)
398 || require_valid_fd (fd)
399 || require_end (p))
400 {
401 hostio_packet_error (own_buf);
402 return;
403 }
404
405 if (fstat (fd, &st) == -1)
406 {
407 hostio_error (own_buf);
408 return;
409 }
410
411 host_to_fileio_stat (&st, &fst);
412
413 bytes_sent = hostio_reply_with_data (own_buf,
414 (char *) &fst, sizeof (fst),
415 new_packet_len);
416
417 /* If the response does not fit into a single packet, do not attempt
418 to return a partial response, but simply fail. */
419 if (bytes_sent < sizeof (fst))
420 write_enn (own_buf);
421 }
422
423 static void
424 handle_close (char *own_buf)
425 {
426 int fd, ret;
427 char *p;
428 struct fd_list **open_fd_p, *old_fd;
429
430 p = own_buf + strlen ("vFile:close:");
431
432 if (require_int (&p, &fd)
433 || require_valid_fd (fd)
434 || require_end (p))
435 {
436 hostio_packet_error (own_buf);
437 return;
438 }
439
440 ret = close (fd);
441
442 if (ret == -1)
443 {
444 hostio_error (own_buf);
445 return;
446 }
447
448 open_fd_p = &open_fds;
449 /* We know that fd is in the list, thanks to require_valid_fd. */
450 while ((*open_fd_p)->fd != fd)
451 open_fd_p = &(*open_fd_p)->next;
452
453 old_fd = *open_fd_p;
454 *open_fd_p = (*open_fd_p)->next;
455 free (old_fd);
456
457 hostio_reply (own_buf, ret);
458 }
459
460 static void
461 handle_unlink (char *own_buf)
462 {
463 char filename[HOSTIO_PATH_MAX];
464 char *p;
465 int ret;
466
467 p = own_buf + strlen ("vFile:unlink:");
468
469 if (require_filename (&p, filename)
470 || require_end (p))
471 {
472 hostio_packet_error (own_buf);
473 return;
474 }
475
476 ret = unlink (filename);
477
478 if (ret == -1)
479 {
480 hostio_error (own_buf);
481 return;
482 }
483
484 hostio_reply (own_buf, ret);
485 }
486
487 static void
488 handle_readlink (char *own_buf, int *new_packet_len)
489 {
490 char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX];
491 char *p;
492 int ret, bytes_sent;
493
494 p = own_buf + strlen ("vFile:readlink:");
495
496 if (require_filename (&p, filename)
497 || require_end (p))
498 {
499 hostio_packet_error (own_buf);
500 return;
501 }
502
503 ret = readlink (filename, linkname, sizeof (linkname) - 1);
504 if (ret == -1)
505 {
506 hostio_error (own_buf);
507 return;
508 }
509
510 bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
511
512 /* If the response does not fit into a single packet, do not attempt
513 to return a partial response, but simply fail. */
514 if (bytes_sent < ret)
515 sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG);
516 }
517
518 /* Handle all the 'F' file transfer packets. */
519
520 int
521 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
522 {
523 if (startswith (own_buf, "vFile:open:"))
524 handle_open (own_buf);
525 else if (startswith (own_buf, "vFile:pread:"))
526 handle_pread (own_buf, new_packet_len);
527 else if (startswith (own_buf, "vFile:pwrite:"))
528 handle_pwrite (own_buf, packet_len);
529 else if (startswith (own_buf, "vFile:fstat:"))
530 handle_fstat (own_buf, new_packet_len);
531 else if (startswith (own_buf, "vFile:close:"))
532 handle_close (own_buf);
533 else if (startswith (own_buf, "vFile:unlink:"))
534 handle_unlink (own_buf);
535 else if (startswith (own_buf, "vFile:readlink:"))
536 handle_readlink (own_buf, new_packet_len);
537 else
538 return 0;
539
540 return 1;
541 }
This page took 0.040358 seconds and 4 git commands to generate.