• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
49 int
sys_read(tcp)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
sys_write(tcp)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
tprint_iov(tcp,len,addr)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
sys_readv(tcp)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
sys_writev(tcp)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
sys_pread(tcp)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
sys_pwrite(tcp)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
sys_sendfile(tcp)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
sys_pread(tcp)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
sys_pwrite(tcp)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
sys_sendfile(tcp)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
sys_sendfile64(tcp)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
sys_pread64(tcp)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
sys_pwrite64(tcp)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
sys_ioctl(tcp)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