/* Host file transfer support for gdbserver.
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
Contributed by CodeSourcery.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
#include "gdb/fileio.h"
{
int input_index, output_index, escaped;
- *data = malloc (p_len);
+ *data = xmalloc (p_len);
output_index = 0;
escaped = 0;
}
if (escaped)
- return -1;
+ {
+ free (*data);
+ return -1;
+ }
*data_len = output_index;
return 0;
}
/* Record the new file descriptor. */
- new_fd = malloc (sizeof (struct fd_list));
+ new_fd = xmalloc (sizeof (struct fd_list));
new_fd->fd = fd;
new_fd->next = open_fds;
open_fds = new_fd;
return;
}
- data = malloc (len);
+ data = xmalloc (len);
#ifdef HAVE_PREAD
ret = pread (fd, data, len, offset);
#else
- ret = lseek (fd, offset, SEEK_SET);
- if (ret != -1)
- ret = read (fd, data, len);
+ ret = -1;
#endif
+ /* If we have no pread or it failed for this file, use lseek/read. */
+ if (ret == -1)
+ {
+ ret = lseek (fd, offset, SEEK_SET);
+ if (ret != -1)
+ ret = read (fd, data, len);
+ }
if (ret == -1)
{
#ifdef HAVE_PWRITE
ret = pwrite (fd, data, len, offset);
#else
- ret = lseek (fd, offset, SEEK_SET);
- if (ret != -1)
- ret = write (fd, data, len);
+ ret = -1;
#endif
+ /* If we have no pwrite or it failed for this file, use lseek/write. */
+ if (ret == -1)
+ {
+ ret = lseek (fd, offset, SEEK_SET);
+ if (ret != -1)
+ ret = write (fd, data, len);
+ }
if (ret == -1)
{
}
open_fd_p = &open_fds;
- while (*open_fd_p && (*open_fd_p)->fd != fd)
+ /* We know that fd is in the list, thanks to require_valid_fd. */
+ while ((*open_fd_p)->fd != fd)
open_fd_p = &(*open_fd_p)->next;
old_fd = *open_fd_p;
hostio_reply (own_buf, ret);
}
+static void
+handle_readlink (char *own_buf, int *new_packet_len)
+{
+#if defined (HAVE_READLINK)
+ char filename[PATH_MAX], linkname[PATH_MAX];
+ char *p;
+ int ret, bytes_sent;
+
+ p = own_buf + strlen ("vFile:readlink:");
+
+ if (require_filename (&p, filename)
+ || require_end (p))
+ {
+ hostio_packet_error (own_buf);
+ return;
+ }
+
+ ret = readlink (filename, linkname, sizeof (linkname) - 1);
+ if (ret == -1)
+ {
+ hostio_error (own_buf);
+ return;
+ }
+
+ bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
+
+ /* If the response does not fit into a single packet, do not attempt
+ to return a partial response, but simply fail. */
+ if (bytes_sent < ret)
+ sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG);
+#else /* ! HAVE_READLINK */
+ sprintf (own_buf, "F-1,%x", FILEIO_ENOSYS);
+#endif
+}
+
/* Handle all the 'F' file transfer packets. */
int
handle_close (own_buf);
else if (strncmp (own_buf, "vFile:unlink:", 13) == 0)
handle_unlink (own_buf);
+ else if (strncmp (own_buf, "vFile:readlink:", 15) == 0)
+ handle_readlink (own_buf, new_packet_len);
else
return 0;