1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) 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 49 int 50 sys_read(tcp) 51 struct 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 65 int 66 sys_write(tcp) 67 struct 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 78 void 79 tprint_iov(tcp, len, addr) 80 struct tcb * tcp; 81 unsigned long len; 82 unsigned 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 127 int 128 sys_readv(tcp) 129 struct 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 145 int 146 sys_writev(tcp) 147 struct 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 160 int 161 sys_pread(tcp) 162 struct 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 182 int 183 sys_pwrite(tcp) 184 struct 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 205 int 206 sys_sendfile(tcp) 207 struct 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 256 int 257 sys_pread(tcp) 258 struct 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 274 int 275 sys_pwrite(tcp) 276 struct 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 288 int 289 sys_sendfile(tcp) 290 struct 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 307 int 308 sys_sendfile64(tcp) 309 struct 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 329 int 330 sys_pread64(tcp) 331 struct 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 347 int 348 sys_pwrite64(tcp) 349 struct 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 362 int 363 sys_ioctl(tcp) 364 struct 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