1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $Id: io.c,v 1.20 2005/06/01 19:22:08 roland Exp $ 31 */ 32 33#include "defs.h" 34 35#include <fcntl.h> 36#if HAVE_SYS_UIO_H 37#include <sys/uio.h> 38#endif 39 40#ifdef HAVE_LONG_LONG_OFF_T 41/* 42 * Hacks for systems that have a long long off_t 43 */ 44 45#define sys_pread64 sys_pread 46#define sys_pwrite64 sys_pwrite 47#endif 48 49int 50sys_read(tcp) 51struct tcb *tcp; 52{ 53 if (entering(tcp)) { 54 tprintf("%ld, ", tcp->u_arg[0]); 55 } else { 56 if (syserror(tcp)) 57 tprintf("%#lx", tcp->u_arg[1]); 58 else 59 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 60 tprintf(", %lu", tcp->u_arg[2]); 61 } 62 return 0; 63} 64 65int 66sys_write(tcp) 67struct tcb *tcp; 68{ 69 if (entering(tcp)) { 70 tprintf("%ld, ", tcp->u_arg[0]); 71 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 72 tprintf(", %lu", tcp->u_arg[2]); 73 } 74 return 0; 75} 76 77#if HAVE_SYS_UIO_H 78void 79tprint_iov(tcp, len, addr) 80struct tcb * tcp; 81unsigned long len; 82unsigned long addr; 83{ 84 struct iovec iov; 85 unsigned long size, cur, end, abbrev_end; 86 int failed = 0; 87 88 if (!len) { 89 tprintf("[]"); 90 return; 91 } 92 size = len * sizeof(iov); 93 end = addr + size; 94 if (!verbose(tcp) || size / sizeof(iov) != len || end < addr) { 95 tprintf("%#lx", addr); 96 return; 97 } 98 if (abbrev(tcp)) { 99 abbrev_end = addr + max_strlen * sizeof(iov); 100 if (abbrev_end < addr) 101 abbrev_end = end; 102 } else { 103 abbrev_end = end; 104 } 105 tprintf("["); 106 for (cur = addr; cur < end; cur += sizeof(iov)) { 107 if (cur > addr) 108 tprintf(", "); 109 if (cur >= abbrev_end) { 110 tprintf("..."); 111 break; 112 } 113 if (umoven(tcp, cur, sizeof iov, (char *) &iov) < 0) { 114 tprintf("?"); 115 failed = 1; 116 break; 117 } 118 tprintf("{"); 119 printstr(tcp, (long) iov.iov_base, iov.iov_len); 120 tprintf(", %lu}", (unsigned long)iov.iov_len); 121 } 122 tprintf("]"); 123 if (failed) 124 tprintf(" %#lx", addr); 125} 126 127int 128sys_readv(tcp) 129struct tcb *tcp; 130{ 131 if (entering(tcp)) { 132 tprintf("%ld, ", tcp->u_arg[0]); 133 } else { 134 if (syserror(tcp)) { 135 tprintf("%#lx, %lu", 136 tcp->u_arg[1], tcp->u_arg[2]); 137 return 0; 138 } 139 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]); 140 tprintf(", %lu", tcp->u_arg[2]); 141 } 142 return 0; 143} 144 145int 146sys_writev(tcp) 147struct tcb *tcp; 148{ 149 if (entering(tcp)) { 150 tprintf("%ld, ", tcp->u_arg[0]); 151 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]); 152 tprintf(", %lu", tcp->u_arg[2]); 153 } 154 return 0; 155} 156#endif 157 158#if defined(SVR4) 159 160int 161sys_pread(tcp) 162struct tcb *tcp; 163{ 164 if (entering(tcp)) { 165 tprintf("%ld, ", tcp->u_arg[0]); 166 } else { 167 if (syserror(tcp)) 168 tprintf("%#lx", tcp->u_arg[1]); 169 else 170 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 171#if UNIXWARE 172 /* off_t is signed int */ 173 tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]); 174#else 175 tprintf(", %lu, %llu", tcp->u_arg[2], 176 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 177#endif 178 } 179 return 0; 180} 181 182int 183sys_pwrite(tcp) 184struct tcb *tcp; 185{ 186 if (entering(tcp)) { 187 tprintf("%ld, ", tcp->u_arg[0]); 188 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 189#if UNIXWARE 190 /* off_t is signed int */ 191 tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]); 192#else 193 tprintf(", %lu, %llu", tcp->u_arg[2], 194 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 195#endif 196 } 197 return 0; 198} 199#endif /* SVR4 */ 200 201#ifdef FREEBSD 202#include <sys/types.h> 203#include <sys/socket.h> 204 205int 206sys_sendfile(tcp) 207struct tcb *tcp; 208{ 209 if (entering(tcp)) { 210 tprintf("%ld, %ld, %llu, %lu", tcp->u_arg[0], tcp->u_arg[1], 211 LONG_LONG(tcp->u_arg[2], tcp->u_arg[3]), 212 tcp->u_arg[4]); 213 } else { 214 off_t offset; 215 216 if (!tcp->u_arg[5]) 217 tprintf(", NULL"); 218 else { 219 struct sf_hdtr hdtr; 220 221 if (umove(tcp, tcp->u_arg[5], &hdtr) < 0) 222 tprintf(", %#lx", tcp->u_arg[5]); 223 else { 224 tprintf(", { "); 225 tprint_iov(tcp, hdtr.hdr_cnt, hdtr.headers); 226 tprintf(", %u, ", hdtr.hdr_cnt); 227 tprint_iov(tcp, hdtr.trl_cnt, hdtr.trailers); 228 tprintf(", %u }", hdtr.hdr_cnt); 229 } 230 } 231 if (!tcp->u_arg[6]) 232 tprintf(", NULL"); 233 else if (umove(tcp, tcp->u_arg[6], &offset) < 0) 234 tprintf(", %#lx", tcp->u_arg[6]); 235 else 236 tprintf(", [%llu]", offset); 237 tprintf(", %lu", tcp->u_arg[7]); 238 } 239 return 0; 240} 241#endif /* FREEBSD */ 242 243#ifdef LINUX 244 245/* The SH4 ABI does allow long longs in odd-numbered registers, but 246 does not allow them to be split between registers and memory - and 247 there are only four argument registers for normal functions. As a 248 result pread takes an extra padding argument before the offset. This 249 was changed late in the 2.4 series (around 2.4.20). */ 250#if defined(SH) 251#define PREAD_OFFSET_ARG 4 252#else 253#define PREAD_OFFSET_ARG 3 254#endif 255 256int 257sys_pread(tcp) 258struct tcb *tcp; 259{ 260 if (entering(tcp)) { 261 tprintf("%ld, ", tcp->u_arg[0]); 262 } else { 263 if (syserror(tcp)) 264 tprintf("%#lx", tcp->u_arg[1]); 265 else 266 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 267 ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */ 268 tprintf(", %lu, %llu", tcp->u_arg[2], 269 *(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]); 270 } 271 return 0; 272} 273 274int 275sys_pwrite(tcp) 276struct tcb *tcp; 277{ 278 if (entering(tcp)) { 279 tprintf("%ld, ", tcp->u_arg[0]); 280 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 281 ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */ 282 tprintf(", %lu, %llu", tcp->u_arg[2], 283 *(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]); 284 } 285 return 0; 286} 287 288int 289sys_sendfile(tcp) 290struct tcb *tcp; 291{ 292 if (entering(tcp)) { 293 off_t offset; 294 295 tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]); 296 if (!tcp->u_arg[2]) 297 tprintf("NULL"); 298 else if (umove(tcp, tcp->u_arg[2], &offset) < 0) 299 tprintf("%#lx", tcp->u_arg[2]); 300 else 301 tprintf("[%lu]", offset); 302 tprintf(", %lu", tcp->u_arg[3]); 303 } 304 return 0; 305} 306 307int 308sys_sendfile64(tcp) 309struct tcb *tcp; 310{ 311 if (entering(tcp)) { 312 loff_t offset; 313 314 tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]); 315 if (!tcp->u_arg[2]) 316 tprintf("NULL"); 317 else if (umove(tcp, tcp->u_arg[2], &offset) < 0) 318 tprintf("%#lx", tcp->u_arg[2]); 319 else 320 tprintf("[%llu]", (unsigned long long int) offset); 321 tprintf(", %lu", tcp->u_arg[3]); 322 } 323 return 0; 324} 325 326#endif /* LINUX */ 327 328#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T 329int 330sys_pread64(tcp) 331struct tcb *tcp; 332{ 333 if (entering(tcp)) { 334 tprintf("%ld, ", tcp->u_arg[0]); 335 } else { 336 ALIGN64 (tcp, 3); 337 if (syserror(tcp)) 338 tprintf("%#lx", tcp->u_arg[1]); 339 else 340 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 341 tprintf(", %lu, %#llx", tcp->u_arg[2], 342 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 343 } 344 return 0; 345} 346 347int 348sys_pwrite64(tcp) 349struct tcb *tcp; 350{ 351 if (entering(tcp)) { 352 ALIGN64 (tcp, 3); 353 tprintf("%ld, ", tcp->u_arg[0]); 354 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 355 tprintf(", %lu, %#llx", tcp->u_arg[2], 356 LONG_LONG(tcp->u_arg[3], tcp->u_arg[4])); 357 } 358 return 0; 359} 360#endif 361 362int 363sys_ioctl(tcp) 364struct tcb *tcp; 365{ 366 const struct ioctlent *iop; 367 368 if (entering(tcp)) { 369 tprintf("%ld, ", tcp->u_arg[0]); 370 iop = ioctl_lookup(tcp->u_arg[1]); 371 if (iop) { 372 tprintf("%s", iop->symbol); 373 while ((iop = ioctl_next_match(iop))) 374 tprintf(" or %s", iop->symbol); 375 } else 376 tprintf("%#lx", tcp->u_arg[1]); 377 ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]); 378 } 379 else { 380 int ret; 381 if (!(ret = ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]))) 382 tprintf(", %#lx", tcp->u_arg[2]); 383 else 384 return ret - 1; 385 } 386 return 0; 387} 388