18dffb485Schristos /* Host file transfer support for gdbserver. 2*f1c2b495Schristos Copyright (C) 2007-2024 Free Software Foundation, Inc. 38dffb485Schristos 48dffb485Schristos Contributed by CodeSourcery. 58dffb485Schristos 68dffb485Schristos This file is part of GDB. 78dffb485Schristos 88dffb485Schristos This program is free software; you can redistribute it and/or modify 98dffb485Schristos it under the terms of the GNU General Public License as published by 108dffb485Schristos the Free Software Foundation; either version 3 of the License, or 118dffb485Schristos (at your option) any later version. 128dffb485Schristos 138dffb485Schristos This program is distributed in the hope that it will be useful, 148dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 158dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 168dffb485Schristos GNU General Public License for more details. 178dffb485Schristos 188dffb485Schristos You should have received a copy of the GNU General Public License 198dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 208dffb485Schristos 214b169a6bSchristos #include "gdbsupport/fileio.h" 228dffb485Schristos #include "hostio.h" 238dffb485Schristos 248dffb485Schristos #include <fcntl.h> 258dffb485Schristos #include <limits.h> 268dffb485Schristos #include <unistd.h> 278dffb485Schristos #include <sys/types.h> 288dffb485Schristos #include <sys/stat.h> 298dffb485Schristos #include "gdbsupport/fileio.h" 308dffb485Schristos 318dffb485Schristos struct fd_list 328dffb485Schristos { 338dffb485Schristos int fd; 348dffb485Schristos struct fd_list *next; 358dffb485Schristos }; 368dffb485Schristos 378dffb485Schristos static struct fd_list *open_fds; 388dffb485Schristos 398dffb485Schristos static int 408dffb485Schristos safe_fromhex (char a, int *nibble) 418dffb485Schristos { 428dffb485Schristos if (a >= '0' && a <= '9') 438dffb485Schristos *nibble = a - '0'; 448dffb485Schristos else if (a >= 'a' && a <= 'f') 458dffb485Schristos *nibble = a - 'a' + 10; 468dffb485Schristos else if (a >= 'A' && a <= 'F') 478dffb485Schristos *nibble = a - 'A' + 10; 488dffb485Schristos else 498dffb485Schristos return -1; 508dffb485Schristos 518dffb485Schristos return 0; 528dffb485Schristos } 538dffb485Schristos 548dffb485Schristos /* Filenames are hex encoded, so the maximum we can handle is half the 558dffb485Schristos packet buffer size. Cap to PATH_MAX, if it is shorter. */ 568dffb485Schristos #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1)) 578dffb485Schristos # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1) 588dffb485Schristos #else 598dffb485Schristos # define HOSTIO_PATH_MAX PATH_MAX 608dffb485Schristos #endif 618dffb485Schristos 628dffb485Schristos static int 638dffb485Schristos require_filename (char **pp, char *filename) 648dffb485Schristos { 658dffb485Schristos int count; 668dffb485Schristos char *p; 678dffb485Schristos 688dffb485Schristos p = *pp; 698dffb485Schristos count = 0; 708dffb485Schristos 718dffb485Schristos while (*p && *p != ',') 728dffb485Schristos { 738dffb485Schristos int nib1, nib2; 748dffb485Schristos 758dffb485Schristos /* Don't allow overflow. */ 768dffb485Schristos if (count >= HOSTIO_PATH_MAX - 1) 778dffb485Schristos return -1; 788dffb485Schristos 798dffb485Schristos if (safe_fromhex (p[0], &nib1) 808dffb485Schristos || safe_fromhex (p[1], &nib2)) 818dffb485Schristos return -1; 828dffb485Schristos 838dffb485Schristos filename[count++] = nib1 * 16 + nib2; 848dffb485Schristos p += 2; 858dffb485Schristos } 868dffb485Schristos 878dffb485Schristos filename[count] = '\0'; 888dffb485Schristos *pp = p; 898dffb485Schristos return 0; 908dffb485Schristos } 918dffb485Schristos 928dffb485Schristos static int 938dffb485Schristos require_int (char **pp, int *value) 948dffb485Schristos { 958dffb485Schristos char *p; 968dffb485Schristos int count, firstdigit; 978dffb485Schristos 988dffb485Schristos p = *pp; 998dffb485Schristos *value = 0; 1008dffb485Schristos count = 0; 1018dffb485Schristos firstdigit = -1; 1028dffb485Schristos 1038dffb485Schristos while (*p && *p != ',') 1048dffb485Schristos { 1058dffb485Schristos int nib; 1068dffb485Schristos 1078dffb485Schristos if (safe_fromhex (p[0], &nib)) 1088dffb485Schristos return -1; 1098dffb485Schristos 1108dffb485Schristos if (firstdigit == -1) 1118dffb485Schristos firstdigit = nib; 1128dffb485Schristos 1138dffb485Schristos /* Don't allow overflow. */ 1148dffb485Schristos if (count >= 8 || (count == 7 && firstdigit >= 0x8)) 1158dffb485Schristos return -1; 1168dffb485Schristos 1178dffb485Schristos *value = *value * 16 + nib; 1188dffb485Schristos p++; 1198dffb485Schristos count++; 1208dffb485Schristos } 1218dffb485Schristos 1228dffb485Schristos *pp = p; 1238dffb485Schristos return 0; 1248dffb485Schristos } 1258dffb485Schristos 1268dffb485Schristos static int 1278dffb485Schristos require_data (char *p, int p_len, char **data, int *data_len) 1288dffb485Schristos { 1298dffb485Schristos int input_index, output_index, escaped; 1308dffb485Schristos 1318dffb485Schristos *data = (char *) xmalloc (p_len); 1328dffb485Schristos 1338dffb485Schristos output_index = 0; 1348dffb485Schristos escaped = 0; 1358dffb485Schristos for (input_index = 0; input_index < p_len; input_index++) 1368dffb485Schristos { 1378dffb485Schristos char b = p[input_index]; 1388dffb485Schristos 1398dffb485Schristos if (escaped) 1408dffb485Schristos { 1418dffb485Schristos (*data)[output_index++] = b ^ 0x20; 1428dffb485Schristos escaped = 0; 1438dffb485Schristos } 1448dffb485Schristos else if (b == '}') 1458dffb485Schristos escaped = 1; 1468dffb485Schristos else 1478dffb485Schristos (*data)[output_index++] = b; 1488dffb485Schristos } 1498dffb485Schristos 1508dffb485Schristos if (escaped) 1518dffb485Schristos { 1528dffb485Schristos free (*data); 1538dffb485Schristos return -1; 1548dffb485Schristos } 1558dffb485Schristos 1568dffb485Schristos *data_len = output_index; 1578dffb485Schristos return 0; 1588dffb485Schristos } 1598dffb485Schristos 1608dffb485Schristos static int 1618dffb485Schristos require_comma (char **pp) 1628dffb485Schristos { 1638dffb485Schristos if (**pp == ',') 1648dffb485Schristos { 1658dffb485Schristos (*pp)++; 1668dffb485Schristos return 0; 1678dffb485Schristos } 1688dffb485Schristos else 1698dffb485Schristos return -1; 1708dffb485Schristos } 1718dffb485Schristos 1728dffb485Schristos static int 1738dffb485Schristos require_end (char *p) 1748dffb485Schristos { 1758dffb485Schristos if (*p == '\0') 1768dffb485Schristos return 0; 1778dffb485Schristos else 1788dffb485Schristos return -1; 1798dffb485Schristos } 1808dffb485Schristos 1818dffb485Schristos static int 1828dffb485Schristos require_valid_fd (int fd) 1838dffb485Schristos { 1848dffb485Schristos struct fd_list *fd_ptr; 1858dffb485Schristos 1868dffb485Schristos for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next) 1878dffb485Schristos if (fd_ptr->fd == fd) 1888dffb485Schristos return 0; 1898dffb485Schristos 1908dffb485Schristos return -1; 1918dffb485Schristos } 1928dffb485Schristos 1934b169a6bSchristos /* Fill BUF with an hostio error packet representing the last hostio 1944b169a6bSchristos error, from errno. */ 1954b169a6bSchristos 1968dffb485Schristos static void 1978dffb485Schristos hostio_error (char *own_buf) 1988dffb485Schristos { 1994b169a6bSchristos int fileio_error = host_to_fileio_error (errno); 2004b169a6bSchristos sprintf (own_buf, "F-1,%x", fileio_error); 2018dffb485Schristos } 2028dffb485Schristos 2038dffb485Schristos static void 2048dffb485Schristos hostio_packet_error (char *own_buf) 2058dffb485Schristos { 2068dffb485Schristos sprintf (own_buf, "F-1,%x", FILEIO_EINVAL); 2078dffb485Schristos } 2088dffb485Schristos 2098dffb485Schristos static void 2108dffb485Schristos hostio_reply (char *own_buf, int result) 2118dffb485Schristos { 2128dffb485Schristos sprintf (own_buf, "F%x", result); 2138dffb485Schristos } 2148dffb485Schristos 2158dffb485Schristos static int 2168dffb485Schristos hostio_reply_with_data (char *own_buf, char *buffer, int len, 2178dffb485Schristos int *new_packet_len) 2188dffb485Schristos { 2198dffb485Schristos int input_index, output_index, out_maxlen; 2208dffb485Schristos 2218dffb485Schristos sprintf (own_buf, "F%x;", len); 2228dffb485Schristos output_index = strlen (own_buf); 2238dffb485Schristos 2248dffb485Schristos out_maxlen = PBUFSIZ; 2258dffb485Schristos 2268dffb485Schristos for (input_index = 0; input_index < len; input_index++) 2278dffb485Schristos { 2288dffb485Schristos char b = buffer[input_index]; 2298dffb485Schristos 2308dffb485Schristos if (b == '$' || b == '#' || b == '}' || b == '*') 2318dffb485Schristos { 2328dffb485Schristos /* These must be escaped. */ 2338dffb485Schristos if (output_index + 2 > out_maxlen) 2348dffb485Schristos break; 2358dffb485Schristos own_buf[output_index++] = '}'; 2368dffb485Schristos own_buf[output_index++] = b ^ 0x20; 2378dffb485Schristos } 2388dffb485Schristos else 2398dffb485Schristos { 2408dffb485Schristos if (output_index + 1 > out_maxlen) 2418dffb485Schristos break; 2428dffb485Schristos own_buf[output_index++] = b; 2438dffb485Schristos } 2448dffb485Schristos } 2458dffb485Schristos 2468dffb485Schristos *new_packet_len = output_index; 2478dffb485Schristos return input_index; 2488dffb485Schristos } 2498dffb485Schristos 2508dffb485Schristos /* Process ID of inferior whose filesystem hostio functions 2518dffb485Schristos that take FILENAME arguments will use. Zero means to use 2528dffb485Schristos our own filesystem. */ 2538dffb485Schristos 2548dffb485Schristos static int hostio_fs_pid; 2558dffb485Schristos 2568dffb485Schristos /* See hostio.h. */ 2578dffb485Schristos 2588dffb485Schristos void 2598dffb485Schristos hostio_handle_new_gdb_connection (void) 2608dffb485Schristos { 2618dffb485Schristos hostio_fs_pid = 0; 2628dffb485Schristos } 2638dffb485Schristos 2648dffb485Schristos /* Handle a "vFile:setfs:" packet. */ 2658dffb485Schristos 2668dffb485Schristos static void 2678dffb485Schristos handle_setfs (char *own_buf) 2688dffb485Schristos { 2698dffb485Schristos char *p; 2708dffb485Schristos int pid; 2718dffb485Schristos 2728dffb485Schristos /* If the target doesn't have any of the in-filesystem-of methods 2738dffb485Schristos then there's no point in GDB sending "vFile:setfs:" packets. We 2748dffb485Schristos reply with an empty packet (i.e. we pretend we don't understand 2758dffb485Schristos "vFile:setfs:") and that should stop GDB sending any more. */ 2768dffb485Schristos if (!the_target->supports_multifs ()) 2778dffb485Schristos { 2788dffb485Schristos own_buf[0] = '\0'; 2798dffb485Schristos return; 2808dffb485Schristos } 2818dffb485Schristos 2828dffb485Schristos p = own_buf + strlen ("vFile:setfs:"); 2838dffb485Schristos 2848dffb485Schristos if (require_int (&p, &pid) 2858dffb485Schristos || pid < 0 2868dffb485Schristos || require_end (p)) 2878dffb485Schristos { 2888dffb485Schristos hostio_packet_error (own_buf); 2898dffb485Schristos return; 2908dffb485Schristos } 2918dffb485Schristos 2928dffb485Schristos hostio_fs_pid = pid; 2938dffb485Schristos 2948dffb485Schristos hostio_reply (own_buf, 0); 2958dffb485Schristos } 2968dffb485Schristos 2978dffb485Schristos static void 2988dffb485Schristos handle_open (char *own_buf) 2998dffb485Schristos { 3008dffb485Schristos char filename[HOSTIO_PATH_MAX]; 3018dffb485Schristos char *p; 3028dffb485Schristos int fileio_flags, fileio_mode, flags, fd; 3038dffb485Schristos mode_t mode; 3048dffb485Schristos struct fd_list *new_fd; 3058dffb485Schristos 3068dffb485Schristos p = own_buf + strlen ("vFile:open:"); 3078dffb485Schristos 3088dffb485Schristos if (require_filename (&p, filename) 3098dffb485Schristos || require_comma (&p) 3108dffb485Schristos || require_int (&p, &fileio_flags) 3118dffb485Schristos || require_comma (&p) 3128dffb485Schristos || require_int (&p, &fileio_mode) 3138dffb485Schristos || require_end (p) 3148dffb485Schristos || fileio_to_host_openflags (fileio_flags, &flags) 3158dffb485Schristos || fileio_to_host_mode (fileio_mode, &mode)) 3168dffb485Schristos { 3178dffb485Schristos hostio_packet_error (own_buf); 3188dffb485Schristos return; 3198dffb485Schristos } 3208dffb485Schristos 3218dffb485Schristos /* We do not need to convert MODE, since the fileio protocol 3228dffb485Schristos uses the standard values. */ 3238dffb485Schristos if (hostio_fs_pid != 0) 3248dffb485Schristos fd = the_target->multifs_open (hostio_fs_pid, filename, flags, mode); 3258dffb485Schristos else 3268dffb485Schristos fd = open (filename, flags, mode); 3278dffb485Schristos 3288dffb485Schristos if (fd == -1) 3298dffb485Schristos { 3308dffb485Schristos hostio_error (own_buf); 3318dffb485Schristos return; 3328dffb485Schristos } 3338dffb485Schristos 3348dffb485Schristos /* Record the new file descriptor. */ 3358dffb485Schristos new_fd = XNEW (struct fd_list); 3368dffb485Schristos new_fd->fd = fd; 3378dffb485Schristos new_fd->next = open_fds; 3388dffb485Schristos open_fds = new_fd; 3398dffb485Schristos 3408dffb485Schristos hostio_reply (own_buf, fd); 3418dffb485Schristos } 3428dffb485Schristos 3438dffb485Schristos static void 3448dffb485Schristos handle_pread (char *own_buf, int *new_packet_len) 3458dffb485Schristos { 3468dffb485Schristos int fd, ret, len, offset, bytes_sent; 3478dffb485Schristos char *p, *data; 3488dffb485Schristos static int max_reply_size = -1; 3498dffb485Schristos 3508dffb485Schristos p = own_buf + strlen ("vFile:pread:"); 3518dffb485Schristos 3528dffb485Schristos if (require_int (&p, &fd) 3538dffb485Schristos || require_comma (&p) 3548dffb485Schristos || require_valid_fd (fd) 3558dffb485Schristos || require_int (&p, &len) 3568dffb485Schristos || require_comma (&p) 3578dffb485Schristos || require_int (&p, &offset) 3588dffb485Schristos || require_end (p)) 3598dffb485Schristos { 3608dffb485Schristos hostio_packet_error (own_buf); 3618dffb485Schristos return; 3628dffb485Schristos } 3638dffb485Schristos 3648dffb485Schristos /* Do not attempt to read more than the maximum number of bytes 3658dffb485Schristos hostio_reply_with_data can fit in a packet. We may still read 3668dffb485Schristos too much because of escaping, but this is handled below. */ 3678dffb485Schristos if (max_reply_size == -1) 3688dffb485Schristos { 3698dffb485Schristos sprintf (own_buf, "F%x;", PBUFSIZ); 3708dffb485Schristos max_reply_size = PBUFSIZ - strlen (own_buf); 3718dffb485Schristos } 3728dffb485Schristos if (len > max_reply_size) 3738dffb485Schristos len = max_reply_size; 3748dffb485Schristos 3758dffb485Schristos data = (char *) xmalloc (len); 3768dffb485Schristos #ifdef HAVE_PREAD 3778dffb485Schristos ret = pread (fd, data, len, offset); 3788dffb485Schristos #else 3798dffb485Schristos ret = -1; 3808dffb485Schristos #endif 3818dffb485Schristos /* If we have no pread or it failed for this file, use lseek/read. */ 3828dffb485Schristos if (ret == -1) 3838dffb485Schristos { 3848dffb485Schristos ret = lseek (fd, offset, SEEK_SET); 3858dffb485Schristos if (ret != -1) 3868dffb485Schristos ret = read (fd, data, len); 3878dffb485Schristos } 3888dffb485Schristos 3898dffb485Schristos if (ret == -1) 3908dffb485Schristos { 3918dffb485Schristos hostio_error (own_buf); 3928dffb485Schristos free (data); 3938dffb485Schristos return; 3948dffb485Schristos } 3958dffb485Schristos 3968dffb485Schristos bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len); 3978dffb485Schristos 3988dffb485Schristos /* If we were using read, and the data did not all fit in the reply, 3998dffb485Schristos we would have to back up using lseek here. With pread it does 4008dffb485Schristos not matter. But we still have a problem; the return value in the 4018dffb485Schristos packet might be wrong, so we must fix it. This time it will 4028dffb485Schristos definitely fit. */ 4038dffb485Schristos if (bytes_sent < ret) 4048dffb485Schristos bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent, 4058dffb485Schristos new_packet_len); 4068dffb485Schristos 4078dffb485Schristos free (data); 4088dffb485Schristos } 4098dffb485Schristos 4108dffb485Schristos static void 4118dffb485Schristos handle_pwrite (char *own_buf, int packet_len) 4128dffb485Schristos { 4138dffb485Schristos int fd, ret, len, offset; 4148dffb485Schristos char *p, *data; 4158dffb485Schristos 4168dffb485Schristos p = own_buf + strlen ("vFile:pwrite:"); 4178dffb485Schristos 4188dffb485Schristos if (require_int (&p, &fd) 4198dffb485Schristos || require_comma (&p) 4208dffb485Schristos || require_valid_fd (fd) 4218dffb485Schristos || require_int (&p, &offset) 4228dffb485Schristos || require_comma (&p) 4238dffb485Schristos || require_data (p, packet_len - (p - own_buf), &data, &len)) 4248dffb485Schristos { 4258dffb485Schristos hostio_packet_error (own_buf); 4268dffb485Schristos return; 4278dffb485Schristos } 4288dffb485Schristos 4298dffb485Schristos #ifdef HAVE_PWRITE 4308dffb485Schristos ret = pwrite (fd, data, len, offset); 4318dffb485Schristos #else 4328dffb485Schristos ret = -1; 4338dffb485Schristos #endif 4348dffb485Schristos /* If we have no pwrite or it failed for this file, use lseek/write. */ 4358dffb485Schristos if (ret == -1) 4368dffb485Schristos { 4378dffb485Schristos ret = lseek (fd, offset, SEEK_SET); 4388dffb485Schristos if (ret != -1) 4398dffb485Schristos ret = write (fd, data, len); 4408dffb485Schristos } 4418dffb485Schristos 4428dffb485Schristos if (ret == -1) 4438dffb485Schristos { 4448dffb485Schristos hostio_error (own_buf); 4458dffb485Schristos free (data); 4468dffb485Schristos return; 4478dffb485Schristos } 4488dffb485Schristos 4498dffb485Schristos hostio_reply (own_buf, ret); 4508dffb485Schristos free (data); 4518dffb485Schristos } 4528dffb485Schristos 4538dffb485Schristos static void 4548dffb485Schristos handle_fstat (char *own_buf, int *new_packet_len) 4558dffb485Schristos { 4568dffb485Schristos int fd, bytes_sent; 4578dffb485Schristos char *p; 4588dffb485Schristos struct stat st; 4598dffb485Schristos struct fio_stat fst; 4608dffb485Schristos 4618dffb485Schristos p = own_buf + strlen ("vFile:fstat:"); 4628dffb485Schristos 4638dffb485Schristos if (require_int (&p, &fd) 4648dffb485Schristos || require_valid_fd (fd) 4658dffb485Schristos || require_end (p)) 4668dffb485Schristos { 4678dffb485Schristos hostio_packet_error (own_buf); 4688dffb485Schristos return; 4698dffb485Schristos } 4708dffb485Schristos 4718dffb485Schristos if (fstat (fd, &st) == -1) 4728dffb485Schristos { 4738dffb485Schristos hostio_error (own_buf); 4748dffb485Schristos return; 4758dffb485Schristos } 4768dffb485Schristos 4778dffb485Schristos host_to_fileio_stat (&st, &fst); 4788dffb485Schristos 4798dffb485Schristos bytes_sent = hostio_reply_with_data (own_buf, 4808dffb485Schristos (char *) &fst, sizeof (fst), 4818dffb485Schristos new_packet_len); 4828dffb485Schristos 4838dffb485Schristos /* If the response does not fit into a single packet, do not attempt 4848dffb485Schristos to return a partial response, but simply fail. */ 4858dffb485Schristos if (bytes_sent < sizeof (fst)) 4868dffb485Schristos write_enn (own_buf); 4878dffb485Schristos } 4888dffb485Schristos 4898dffb485Schristos static void 4908dffb485Schristos handle_close (char *own_buf) 4918dffb485Schristos { 4928dffb485Schristos int fd, ret; 4938dffb485Schristos char *p; 4948dffb485Schristos struct fd_list **open_fd_p, *old_fd; 4958dffb485Schristos 4968dffb485Schristos p = own_buf + strlen ("vFile:close:"); 4978dffb485Schristos 4988dffb485Schristos if (require_int (&p, &fd) 4998dffb485Schristos || require_valid_fd (fd) 5008dffb485Schristos || require_end (p)) 5018dffb485Schristos { 5028dffb485Schristos hostio_packet_error (own_buf); 5038dffb485Schristos return; 5048dffb485Schristos } 5058dffb485Schristos 5068dffb485Schristos ret = close (fd); 5078dffb485Schristos 5088dffb485Schristos if (ret == -1) 5098dffb485Schristos { 5108dffb485Schristos hostio_error (own_buf); 5118dffb485Schristos return; 5128dffb485Schristos } 5138dffb485Schristos 5148dffb485Schristos open_fd_p = &open_fds; 5158dffb485Schristos /* We know that fd is in the list, thanks to require_valid_fd. */ 5168dffb485Schristos while ((*open_fd_p)->fd != fd) 5178dffb485Schristos open_fd_p = &(*open_fd_p)->next; 5188dffb485Schristos 5198dffb485Schristos old_fd = *open_fd_p; 5208dffb485Schristos *open_fd_p = (*open_fd_p)->next; 5218dffb485Schristos free (old_fd); 5228dffb485Schristos 5238dffb485Schristos hostio_reply (own_buf, ret); 5248dffb485Schristos } 5258dffb485Schristos 5268dffb485Schristos static void 5278dffb485Schristos handle_unlink (char *own_buf) 5288dffb485Schristos { 5298dffb485Schristos char filename[HOSTIO_PATH_MAX]; 5308dffb485Schristos char *p; 5318dffb485Schristos int ret; 5328dffb485Schristos 5338dffb485Schristos p = own_buf + strlen ("vFile:unlink:"); 5348dffb485Schristos 5358dffb485Schristos if (require_filename (&p, filename) 5368dffb485Schristos || require_end (p)) 5378dffb485Schristos { 5388dffb485Schristos hostio_packet_error (own_buf); 5398dffb485Schristos return; 5408dffb485Schristos } 5418dffb485Schristos 5428dffb485Schristos if (hostio_fs_pid != 0) 5438dffb485Schristos ret = the_target->multifs_unlink (hostio_fs_pid, filename); 5448dffb485Schristos else 5458dffb485Schristos ret = unlink (filename); 5468dffb485Schristos 5478dffb485Schristos if (ret == -1) 5488dffb485Schristos { 5498dffb485Schristos hostio_error (own_buf); 5508dffb485Schristos return; 5518dffb485Schristos } 5528dffb485Schristos 5538dffb485Schristos hostio_reply (own_buf, ret); 5548dffb485Schristos } 5558dffb485Schristos 5568dffb485Schristos static void 5578dffb485Schristos handle_readlink (char *own_buf, int *new_packet_len) 5588dffb485Schristos { 5598dffb485Schristos char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX]; 5608dffb485Schristos char *p; 5618dffb485Schristos int ret, bytes_sent; 5628dffb485Schristos 5638dffb485Schristos p = own_buf + strlen ("vFile:readlink:"); 5648dffb485Schristos 5658dffb485Schristos if (require_filename (&p, filename) 5668dffb485Schristos || require_end (p)) 5678dffb485Schristos { 5688dffb485Schristos hostio_packet_error (own_buf); 5698dffb485Schristos return; 5708dffb485Schristos } 5718dffb485Schristos 5728dffb485Schristos if (hostio_fs_pid != 0) 5738dffb485Schristos ret = the_target->multifs_readlink (hostio_fs_pid, filename, 5748dffb485Schristos linkname, 5758dffb485Schristos sizeof (linkname) - 1); 5768dffb485Schristos else 5778dffb485Schristos ret = readlink (filename, linkname, sizeof (linkname) - 1); 5788dffb485Schristos 5798dffb485Schristos if (ret == -1) 5808dffb485Schristos { 5818dffb485Schristos hostio_error (own_buf); 5828dffb485Schristos return; 5838dffb485Schristos } 5848dffb485Schristos 5858dffb485Schristos bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len); 5868dffb485Schristos 5878dffb485Schristos /* If the response does not fit into a single packet, do not attempt 5888dffb485Schristos to return a partial response, but simply fail. */ 5898dffb485Schristos if (bytes_sent < ret) 5908dffb485Schristos sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG); 5918dffb485Schristos } 5928dffb485Schristos 5938dffb485Schristos /* Handle all the 'F' file transfer packets. */ 5948dffb485Schristos 5958dffb485Schristos int 5968dffb485Schristos handle_vFile (char *own_buf, int packet_len, int *new_packet_len) 5978dffb485Schristos { 5988dffb485Schristos if (startswith (own_buf, "vFile:open:")) 5998dffb485Schristos handle_open (own_buf); 6008dffb485Schristos else if (startswith (own_buf, "vFile:pread:")) 6018dffb485Schristos handle_pread (own_buf, new_packet_len); 6028dffb485Schristos else if (startswith (own_buf, "vFile:pwrite:")) 6038dffb485Schristos handle_pwrite (own_buf, packet_len); 6048dffb485Schristos else if (startswith (own_buf, "vFile:fstat:")) 6058dffb485Schristos handle_fstat (own_buf, new_packet_len); 6068dffb485Schristos else if (startswith (own_buf, "vFile:close:")) 6078dffb485Schristos handle_close (own_buf); 6088dffb485Schristos else if (startswith (own_buf, "vFile:unlink:")) 6098dffb485Schristos handle_unlink (own_buf); 6108dffb485Schristos else if (startswith (own_buf, "vFile:readlink:")) 6118dffb485Schristos handle_readlink (own_buf, new_packet_len); 6128dffb485Schristos else if (startswith (own_buf, "vFile:setfs:")) 6138dffb485Schristos handle_setfs (own_buf); 6148dffb485Schristos else 6158dffb485Schristos return 0; 6168dffb485Schristos 6178dffb485Schristos return 1; 6188dffb485Schristos } 619