]> granicus.if.org Git - strace/blob - file.c
e528bf28ad14eeb207e29c9d465e7f2b40caac3f
[strace] / file.c
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  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #include <dirent.h>
35
36 #include <sys/stat.h>
37 #ifdef linux
38 #include <asm/stat.h>
39 #endif
40 #include <fcntl.h>
41
42 #ifdef SVR4
43 #  include <sys/cred.h>
44 #endif /* SVR4 */
45
46 #include <sys/vfs.h>
47
48 #ifdef MAJOR_IN_SYSMACROS
49 #include <sys/sysmacros.h>
50 #endif
51
52 #ifdef MAJOR_IN_MKDEV
53 #include <sys/mkdev.h>
54 #endif
55
56 #ifdef HAVE_SYS_ASYNCH_H
57 #include <sys/asynch.h>
58 #endif
59
60 #ifdef SUNOS4
61 #include <ustat.h>
62 #endif
63
64 /*
65  * This is a really dirty trick but it should always work.  Traditional
66  * Unix says r/w/rw are 0/1/2, so we make them true flags 1/2/3 by
67  * adding 1.  Just remember to add 1 to any arg decoded with openmodes.
68  */
69 struct xlat openmodes[] = {
70         { O_RDWR+1,     "O_RDWR"        },
71         { O_RDONLY+1,   "O_RDONLY"      },
72         { O_WRONLY+1,   "O_WRONLY"      },
73         { O_NONBLOCK,   "O_NONBLOCK"    },
74         { O_APPEND,     "O_APPEND"      },
75         { O_CREAT,      "O_CREAT"       },
76         { O_TRUNC,      "O_TRUNC"       },
77         { O_EXCL,       "O_EXCL"        },
78         { O_NOCTTY,     "O_NOCTTY"      },
79 #ifdef O_SYNC
80         { O_SYNC,       "O_SYNC"        },
81 #endif
82 #ifdef O_ASYNC
83         { O_ASYNC,      "O_ASYNC"       },
84 #endif
85 #ifdef O_DSYNC
86         { O_DSYNC,      "O_DSYNC"       },
87 #endif
88 #ifdef O_RSYNC
89         { O_RSYNC,      "O_RSYNC"       },
90 #endif
91 #ifdef O_NDELAY
92         { O_NDELAY,     "O_NDELAY"      },
93 #endif
94 #ifdef O_PRIV
95         { O_PRIV,       "O_PRIV"        },
96 #endif
97 #ifdef O_DIRECT
98    { O_DIRECT, "O_DIRECT"  },
99 #endif
100 #ifdef O_LARGEFILE
101    { O_LARGEFILE,  "O_LARGEFILE"   },
102 #endif
103 #ifdef O_DIRECTORY
104    { O_DIRECTORY,  "O_DIRECTORY"   },
105 #endif
106
107 #ifdef FNDELAY
108         { FNDELAY,      "FNDELAY"       },
109 #endif
110 #ifdef FAPPEND
111         { FAPPEND,      "FAPPEND"       },
112 #endif
113 #ifdef FMARK
114         { FMARK,        "FMARK"         },
115 #endif
116 #ifdef FDEFER
117         { FDEFER,       "FDEFER"        },
118 #endif
119 #ifdef FASYNC
120         { FASYNC,       "FASYNC"        },
121 #endif
122 #ifdef FSHLOCK
123         { FSHLOCK,      "FSHLOCK"       },
124 #endif
125 #ifdef FEXLOCK
126         { FEXLOCK,      "FEXLOCK"       },
127 #endif
128 #ifdef FCREAT
129         { FCREAT,       "FCREAT"        },
130 #endif
131 #ifdef FTRUNC
132         { FTRUNC,       "FTRUNC"        },
133 #endif
134 #ifdef FEXCL
135         { FEXCL,        "FEXCL"         },
136 #endif
137 #ifdef FNBIO
138         { FNBIO,        "FNBIO"         },
139 #endif
140 #ifdef FSYNC
141         { FSYNC,        "FSYNC"         },
142 #endif
143 #ifdef FNOCTTY
144         { FNOCTTY,      "FNOCTTY"       },
145 #endif
146         { 0,            NULL            },
147 };
148
149 int
150 sys_open(tcp)
151 struct tcb *tcp;
152 {
153         if (entering(tcp)) {
154                 printpath(tcp, tcp->u_arg[0]);
155                 tprintf(", ");
156                 /* flags */
157                 printflags(openmodes, tcp->u_arg[1] + 1);
158                 if (tcp->u_arg[1] & O_CREAT) {
159                         /* mode */
160                         tprintf(", %#lo", tcp->u_arg[2]);
161                 }
162         }
163         return 0;
164 }
165
166 #ifdef LINUXSPARC
167 struct xlat openmodessol[] = {
168         { 0,            "O_RDWR"        },
169         { 1,            "O_RDONLY"      },
170         { 2,            "O_WRONLY"      },
171         { 0x80,         "O_NONBLOCK"    },
172         { 8,            "O_APPEND"      },
173         { 0x100,        "O_CREAT"       },
174         { 0x200,        "O_TRUNC"       },
175         { 0x400,        "O_EXCL"        },
176         { 0x800,        "O_NOCTTY"      },
177         { 0x10,         "O_SYNC"        },
178         { 0x40,         "O_DSYNC"       },
179         { 0x8000,       "O_RSYNC"       },
180         { 4,            "O_NDELAY"      },
181         { 0x1000,       "O_PRIV"        },
182         { 0,            NULL            },
183 };
184
185 int
186 solaris_open(tcp)
187 struct tcb *tcp;
188 {
189         if (entering(tcp)) {
190                 printpath(tcp, tcp->u_arg[0]);
191                 tprintf(", ");
192                 /* flags */
193                 printflags(openmodessol, tcp->u_arg[1] + 1);
194                 if (tcp->u_arg[1] & 0x100) {
195                         /* mode */
196                         tprintf(", %#lo", tcp->u_arg[2]);
197                 }
198         }
199         return 0;
200 }
201
202 #endif
203
204 int
205 sys_creat(tcp)
206 struct tcb *tcp;
207 {
208         if (entering(tcp)) {
209                 printpath(tcp, tcp->u_arg[0]);
210                 tprintf(", %#lo", tcp->u_arg[1]);
211         }
212         return 0;
213 }
214
215 static struct xlat access_flags[] = {
216         { F_OK,         "F_OK",         },
217         { R_OK,         "R_OK"          },
218         { W_OK,         "W_OK"          },
219         { X_OK,         "X_OK"          },
220 #ifdef EFF_ONLY_OK
221         { EFF_ONLY_OK,  "EFF_ONLY_OK"   },
222 #endif
223 #ifdef EX_OK
224         { EX_OK,        "EX_OK"         },
225 #endif
226         { 0,            NULL            },
227 };
228
229 int
230 sys_access(tcp)
231 struct tcb *tcp;
232 {
233         if (entering(tcp)) {
234                 printpath(tcp, tcp->u_arg[0]);
235                 tprintf(", ");
236                 printflags(access_flags, tcp->u_arg[1]);
237         }
238         return 0;
239 }
240
241 int
242 sys_umask(tcp)
243 struct tcb *tcp;
244 {
245         if (entering(tcp)) {
246                 tprintf("%#lo", tcp->u_arg[0]);
247         }
248         return RVAL_OCTAL;
249 }
250
251 static struct xlat whence[] = {
252         { SEEK_SET,     "SEEK_SET"      },
253         { SEEK_CUR,     "SEEK_CUR"      },
254         { SEEK_END,     "SEEK_END"      },
255         { 0,            NULL            },
256 };
257
258 int
259 sys_lseek(tcp)
260 struct tcb *tcp;
261 {
262         if (entering(tcp)) {
263                 tprintf("%ld, ", tcp->u_arg[0]);
264                 if (tcp->u_arg[2] == SEEK_SET)
265                         tprintf("%lu, ", tcp->u_arg[1]);
266                 else
267                         tprintf("%ld, ", tcp->u_arg[1]);
268                 printxval(whence, tcp->u_arg[2], "SEEK_???");
269         }
270         return RVAL_UDECIMAL;
271 }
272
273 #ifdef linux
274 int
275 sys_llseek (tcp)
276 struct tcb *tcp;
277 {
278     if (entering(tcp)) {
279         if (tcp->u_arg[4] == SEEK_SET)
280             tprintf("%ld, %llu, ", tcp->u_arg[0],
281                     (((unsigned long long int) tcp->u_arg[1]) << 32
282                      | (unsigned long) tcp->u_arg[2]));
283         else
284             tprintf("%ld, %lld, ", tcp->u_arg[0],
285                     (((long long int) tcp->u_arg[1]) << 32
286                      | (unsigned long) tcp->u_arg[2]));
287     }
288     else {
289         if (syserror(tcp))
290             tprintf("%#lx, ", tcp->u_arg[3]);
291         else {
292             long long int off;
293             umove(tcp, tcp->u_arg[3], &off);
294             tprintf("{%lld}, ", off);
295         }
296         printxval(whence, tcp->u_arg[4], "SEEK_???");
297     }
298     return 0;
299 }
300 #endif
301
302 int
303 sys_truncate(tcp)
304 struct tcb *tcp;
305 {
306         if (entering(tcp)) {
307                 printpath(tcp, tcp->u_arg[0]);
308                 tprintf(", %lu", tcp->u_arg[1]);
309         }
310         return 0;
311 }
312
313 int
314 sys_ftruncate(tcp)
315 struct tcb *tcp;
316 {
317         if (entering(tcp)) {
318                 tprintf("%ld, %lu", tcp->u_arg[0], tcp->u_arg[1]);
319         }
320         return 0;
321 }
322
323 /* several stats */
324
325 static struct xlat modetypes[] = {
326         { S_IFREG,      "S_IFREG"       },
327         { S_IFSOCK,     "S_IFSOCK"      },
328         { S_IFIFO,      "S_IFIFO"       },
329         { S_IFLNK,      "S_IFLNK"       },
330         { S_IFDIR,      "S_IFDIR"       },
331         { S_IFBLK,      "S_IFBLK"       },
332         { S_IFCHR,      "S_IFCHR"       },
333         { 0,            NULL            },
334 };
335
336 static char *
337 sprintmode(mode)
338 int mode;
339 {
340         static char buf[64];
341         char *s;
342
343         if ((mode & S_IFMT) == 0)
344                 s = "";
345         else if ((s = xlookup(modetypes, mode & S_IFMT)) == NULL) {
346                 sprintf(buf, "%#o", mode);
347                 return buf;
348         }
349         sprintf(buf, "%s%s%s%s", s,
350                 (mode & S_ISUID) ? "|S_ISUID" : "",
351                 (mode & S_ISGID) ? "|S_ISGID" : "",
352                 (mode & S_ISVTX) ? "|S_ISVTX" : "");
353         mode &= ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX);
354         if (mode)
355                 sprintf(buf + strlen(buf), "|%#o", mode);
356         s = (*buf == '|') ? buf + 1 : buf;
357         return *s ? s : "0";
358 }
359
360 static char *
361 sprinttime(t)
362 time_t t;
363 {
364         struct tm *tmp;
365         static char buf[32];
366
367         if (t == 0) {
368                 sprintf(buf, "0");
369                 return buf;
370         }
371         tmp = localtime(&t);
372         sprintf(buf, "%02d/%02d/%02d-%02d:%02d:%02d",
373                 tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday,
374                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
375         return buf;
376 }
377
378 #ifdef LINUXSPARC
379 typedef struct {
380         int     tv_sec;
381         int     tv_nsec;
382 } timestruct_t;
383
384 struct solstat {
385         unsigned        st_dev;
386         int             st_pad1[3];     /* network id */
387         unsigned        st_ino;
388         unsigned        st_mode;
389         unsigned        st_nlink;
390         unsigned        st_uid;
391         unsigned        st_gid;
392         unsigned        st_rdev;
393         int             st_pad2[2];
394         int             st_size;
395         int             st_pad3;        /* st_size, off_t expansion */
396         timestruct_t    st_atime;
397         timestruct_t    st_mtime;
398         timestruct_t    st_ctime;
399         int             st_blksize;
400         int             st_blocks;
401         char            st_fstype[16];
402         int             st_pad4[8];     /* expansion area */
403 };
404
405 static void
406 printstatsol(tcp, addr)
407 struct tcb *tcp;
408 int addr;
409 {
410         struct solstat statbuf;
411
412         if (!addr) {
413                 tprintf("NULL");
414                 return;
415         }
416         if (syserror(tcp) || !verbose(tcp)) {
417                 tprintf("%#x", addr);
418                 return;
419         }
420         if (umove(tcp, addr, &statbuf) < 0) {
421                 tprintf("{...}");
422                 return;
423         }
424         if (!abbrev(tcp)) {
425                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
426                         (unsigned long) ((statbuf.st_dev >> 18) & 0x3fff),
427                         (unsigned long) (statbuf.st_dev & 0x3ffff),
428                         (unsigned long) statbuf.st_ino,
429                         sprintmode(statbuf.st_mode));
430                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
431                         (unsigned long) statbuf.st_nlink,
432                         (unsigned long) statbuf.st_uid,
433                         (unsigned long) statbuf.st_gid);
434                 tprintf("st_blksize=%lu, ", (unsigned long) statbuf.st_blksize);
435                 tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
436         }
437         else
438                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
439         switch (statbuf.st_mode & S_IFMT) {
440         case S_IFCHR: case S_IFBLK:
441                 tprintf("st_rdev=makedev(%lu, %lu), ",
442                         (unsigned long) ((statbuf.st_rdev >> 18) & 0x3fff),
443                         (unsigned long) (statbuf.st_rdev & 0x3ffff));
444                 break;
445         default:
446                 tprintf("st_size=%u, ", statbuf.st_size);
447                 break;
448         }
449         if (!abbrev(tcp)) {
450                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
451                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
452                 tprintf("st_ctime=%s}", sprinttime(statbuf.st_ctime));
453         }
454         else
455                 tprintf("...}");
456 }
457 #endif
458
459 static void
460 realprintstat(tcp, statbuf)
461 struct tcb *tcp;
462 #ifdef linux
463 struct new_stat *statbuf;
464 #else
465 struct stat *statbuf;
466 #endif
467 {
468     if (!abbrev(tcp)) {
469             tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
470                     (unsigned long) major(statbuf->st_dev),
471                     (unsigned long) minor(statbuf->st_dev),
472                     (unsigned long) statbuf->st_ino,
473                     sprintmode(statbuf->st_mode));
474             tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
475                     (unsigned long) statbuf->st_nlink,
476                     (unsigned long) statbuf->st_uid,
477                     (unsigned long) statbuf->st_gid);
478 #ifdef HAVE_ST_BLKSIZE
479             tprintf("st_blksize=%lu, ", (unsigned long) statbuf->st_blksize);
480 #endif /* HAVE_ST_BLKSIZE */
481 #ifdef HAVE_ST_BLOCKS
482             tprintf("st_blocks=%lu, ", (unsigned long) statbuf->st_blocks);
483 #endif /* HAVE_ST_BLOCKS */
484     }
485     else
486             tprintf("{st_mode=%s, ", sprintmode(statbuf->st_mode));
487     switch (statbuf->st_mode & S_IFMT) {
488     case S_IFCHR: case S_IFBLK:
489 #ifdef HAVE_ST_RDEV
490             tprintf("st_rdev=makedev(%lu, %lu), ",
491                     (unsigned long) major(statbuf->st_rdev),
492                     (unsigned long) minor(statbuf->st_rdev));
493 #else /* !HAVE_ST_RDEV */
494             tprintf("st_size=makedev(%lu, %lu), ",
495                     (unsigned long) major(statbuf->st_size),
496                     (unsigned long) minor(statbuf->st_size));
497 #endif /* !HAVE_ST_RDEV */
498             break;
499     default:
500             tprintf("st_size=%lu, ", statbuf->st_size);
501             break;
502     }
503     if (!abbrev(tcp)) {
504             tprintf("st_atime=%s, ", sprinttime(statbuf->st_atime));
505             tprintf("st_mtime=%s, ", sprinttime(statbuf->st_mtime));
506             tprintf("st_ctime=%s}", sprinttime(statbuf->st_ctime));
507     }
508     else
509             tprintf("...}");
510 }
511
512
513 static void
514 printstat(tcp, addr)
515 struct tcb *tcp;
516 int addr;
517 {
518 #ifdef linux
519         struct new_stat statbuf;
520 #else
521         struct stat statbuf;
522 #endif
523
524 #ifdef LINUXSPARC
525         if (current_personality == 1) {
526                 printstatsol(tcp, addr);
527                 return;
528         }
529 #endif /* LINUXSPARC */
530
531         if (!addr) {
532                 tprintf("NULL");
533                 return;
534         }
535         if (syserror(tcp) || !verbose(tcp)) {
536                 tprintf("%#x", addr);
537                 return;
538         }
539         if (umove(tcp, addr, &statbuf) < 0) {
540                 tprintf("{...}");
541                 return;
542         }
543
544         realprintstat(tcp, &statbuf);
545 }
546
547 #ifdef linux
548 static void
549 convertoldstat(oldbuf, newbuf)
550 const struct old_stat *oldbuf;
551 struct new_stat *newbuf;
552 {
553     newbuf->st_dev=oldbuf->st_dev;
554     newbuf->st_ino=oldbuf->st_ino;
555     newbuf->st_mode=oldbuf->st_mode;
556     newbuf->st_nlink=oldbuf->st_nlink;
557     newbuf->st_uid=oldbuf->st_uid;
558     newbuf->st_gid=oldbuf->st_gid;
559     newbuf->st_rdev=oldbuf->st_rdev;
560     newbuf->st_size=oldbuf->st_size;
561     newbuf->st_atime=oldbuf->st_atime;
562     newbuf->st_mtime=oldbuf->st_mtime;
563     newbuf->st_ctime=oldbuf->st_ctime;
564     newbuf->st_blksize=0;       /* not supported in old_stat */
565     newbuf->st_blocks=0;                /* not supported in old_stat */
566 }
567 #endif
568
569
570 #ifdef linux
571 static void
572 printoldstat(tcp, addr)
573 struct tcb *tcp;
574 int addr;
575 {
576         struct old_stat statbuf;
577         struct new_stat newstatbuf;
578
579 #ifdef LINUXSPARC
580         if (current_personality == 1) {
581                 printstatsol(tcp, addr);
582                 return;
583         }
584 #endif /* LINUXSPARC */
585
586         if (!addr) {
587                 tprintf("NULL");
588                 return;
589         }
590         if (syserror(tcp) || !verbose(tcp)) {
591                 tprintf("%#x", addr);
592                 return;
593         }
594         if (umove(tcp, addr, &statbuf) < 0) {
595                 tprintf("{...}");
596                 return;
597         }
598
599         convertoldstat(&statbuf, &newstatbuf);
600         realprintstat(tcp, &newstatbuf);
601 }
602 #endif
603
604
605 int
606 sys_stat(tcp)
607 struct tcb *tcp;
608 {
609         if (entering(tcp)) {
610                 printpath(tcp, tcp->u_arg[0]);
611                 tprintf(", ");
612         } else {
613                 printstat(tcp, tcp->u_arg[1]);
614         }
615         return 0;
616 }
617
618 #ifdef linux
619 int
620 sys_oldstat(tcp)
621 struct tcb *tcp;
622 {
623         if (entering(tcp)) {
624                 printpath(tcp, tcp->u_arg[0]);
625                 tprintf(", ");
626         } else {
627                 printoldstat(tcp, tcp->u_arg[1]);
628         }
629         return 0;
630 }
631 #endif
632
633 int
634 sys_fstat(tcp)
635 struct tcb *tcp;
636 {
637         if (entering(tcp))
638                 tprintf("%ld, ", tcp->u_arg[0]);
639         else {
640                 printstat(tcp, tcp->u_arg[1]);
641         }
642         return 0;
643 }
644
645 #ifdef linux
646 int
647 sys_oldfstat(tcp)
648 struct tcb *tcp;
649 {
650         if (entering(tcp))
651                 tprintf("%ld, ", tcp->u_arg[0]);
652         else {
653                 printoldstat(tcp, tcp->u_arg[1]);
654         }
655         return 0;
656 }
657 #endif
658
659 int
660 sys_lstat(tcp)
661 struct tcb *tcp;
662 {
663         if (entering(tcp)) {
664                 printpath(tcp, tcp->u_arg[0]);
665                 tprintf(", ");
666         } else {
667                 printstat(tcp, tcp->u_arg[1]);
668         }
669         return 0;
670 }
671
672 #ifdef linux
673 int
674 sys_oldlstat(tcp)
675 struct tcb *tcp;
676 {
677         if (entering(tcp)) {
678                 printpath(tcp, tcp->u_arg[0]);
679                 tprintf(", ");
680         } else {
681                 printoldstat(tcp, tcp->u_arg[1]);
682         }
683         return 0;
684 }
685 #endif
686
687
688 #if defined(SVR4) || defined(LINUXSPARC)
689
690 int
691 sys_xstat(tcp)
692 struct tcb *tcp;
693 {
694         if (entering(tcp)) {
695                 tprintf("%ld, ", tcp->u_arg[0]);
696                 printpath(tcp, tcp->u_arg[1]);
697                 tprintf(", ");
698         } else {
699                 printstat(tcp, tcp->u_arg[2]);
700         }
701         return 0;
702 }
703
704 int
705 sys_fxstat(tcp)
706 struct tcb *tcp;
707 {
708         if (entering(tcp))
709                 tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
710         else {
711                 printstat(tcp, tcp->u_arg[2]);
712         }
713         return 0;
714 }
715
716 int
717 sys_lxstat(tcp)
718 struct tcb *tcp;
719 {
720         if (entering(tcp)) {
721                 tprintf("%ld, ", tcp->u_arg[0]);
722                 printpath(tcp, tcp->u_arg[1]);
723                 tprintf(", ");
724         } else {
725                 printstat(tcp, tcp->u_arg[2]);
726         }
727         return 0;
728 }
729
730 int
731 sys_xmknod(tcp)
732 struct tcb *tcp;
733 {
734         int mode = tcp->u_arg[2];
735
736         if (entering(tcp)) {
737                 tprintf("%ld, ", tcp->u_arg[0]);
738                 printpath(tcp, tcp->u_arg[1]);
739                 tprintf(", %s", sprintmode(mode));
740                 switch (mode & S_IFMT) {
741                 case S_IFCHR: case S_IFBLK:
742 #ifdef LINUXSPARC
743                         tprintf(", makedev(%lu, %lu)",
744                                 (unsigned long) ((tcp->u_arg[3] >> 18) & 0x3fff),
745                                 (unsigned long) (tcp->u_arg[3] & 0x3ffff));
746 #else           
747                         tprintf(", makedev(%lu, %lu)",
748                                 (unsigned long) major(tcp->u_arg[3]),
749                                 (unsigned long) minor(tcp->u_arg[3]));
750 #endif                          
751                         break;
752                 default:
753                         break;
754                 }
755         }
756         return 0;
757 }
758
759 #endif /* SVR4 || LINUXSPARC */
760
761 #ifdef linux
762
763 static struct xlat fsmagic[] = {
764         { 0xef51,       "EXT2_OLD_SUPER_MAGIC"  },
765         { 0xef53,       "EXT2_SUPER_MAGIC"      },
766         { 0x137d,       "EXT_SUPER_MAGIC"       },
767         { 0x9660,       "ISOFS_SUPER_MAGIC"     },
768         { 0x137f,       "MINIX_SUPER_MAGIC"     },
769         { 0x138f,       "MINIX_SUPER_MAGIC2"    },
770         { 0x2468,       "NEW_MINIX_SUPER_MAGIC" },
771         { 0x4d44,       "MSDOS_SUPER_MAGIC"     },
772         { 0x6969,       "NFS_SUPER_MAGIC"       },
773         { 0x9fa0,       "PROC_SUPER_MAGIC"      },
774         { 0x012fd16d,   "XIAFS_SUPER_MAGIC"     },
775         { 0,            NULL                    },
776 };
777
778 #endif /* linux */
779
780 #ifndef SVR4
781
782 static char *
783 sprintfstype(magic)
784 int magic;
785 {
786         static char buf[32];
787 #ifdef linux
788         char *s;
789
790         s = xlookup(fsmagic, magic);
791         if (s) {
792                 sprintf(buf, "\"%s\"", s);
793                 return buf;
794         }
795 #endif /* linux */
796         sprintf(buf, "%#x", magic);
797         return buf;
798 }
799
800 static void
801 printstatfs(tcp, addr)
802 struct tcb *tcp;
803 long addr;
804 {
805         struct statfs statbuf;
806
807         if (syserror(tcp) || !verbose(tcp)) {
808                 tprintf("%#lx", addr);
809                 return;
810         }
811         if (umove(tcp, addr, &statbuf) < 0) {
812                 tprintf("{...}");
813                 return;
814         }
815 #ifdef ALPHA
816
817         tprintf("{f_type=%s, f_fbsize=%u, f_blocks=%u, f_bfree=%u, ",
818                 sprintfstype(statbuf.f_type),
819                 statbuf.f_bsize, statbuf.f_blocks, statbuf.f_bfree);
820         tprintf("f_bavail=%u, f_files=%u, f_ffree=%u, f_namelen=%u}",
821                 statbuf.f_bavail,statbuf.f_files, statbuf.f_ffree, statbuf.f_namelen);
822 #else /* !ALPHA */
823         tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%lu, f_bfree=%lu, ",
824                 sprintfstype(statbuf.f_type),
825                 (unsigned long)statbuf.f_bsize,
826                 (unsigned long)statbuf.f_blocks,
827                 (unsigned long)statbuf.f_bfree);
828         tprintf("f_files=%lu, f_ffree=%lu",
829                 (unsigned long)statbuf.f_files,
830                 (unsigned long)statbuf.f_ffree);
831 #ifdef linux
832         tprintf(", f_namelen=%lu}", (unsigned long)statbuf.f_namelen);
833 #endif /* linux */
834 #endif /* !ALPHA */
835         tprintf("}");
836 }
837
838 int
839 sys_statfs(tcp)
840 struct tcb *tcp;
841 {
842         if (entering(tcp)) {
843                 printpath(tcp, tcp->u_arg[0]);
844                 tprintf(", ");
845         } else {
846                 printstatfs(tcp, tcp->u_arg[1]);
847         }
848         return 0;
849 }
850
851 int
852 sys_fstatfs(tcp)
853 struct tcb *tcp;
854 {
855         if (entering(tcp)) {
856                 tprintf("%lu, ", tcp->u_arg[0]);
857         } else {
858                 printstatfs(tcp, tcp->u_arg[1]);
859         }
860         return 0;
861 }
862
863 #if defined(linux) && defined(alpha)
864
865 int
866 osf_statfs(tcp)
867 struct tcb *tcp;
868 {
869         if (entering(tcp)) {
870                 printpath(tcp, tcp->u_arg[0]);
871                 tprintf(", ");
872         } else {
873                 printstatfs(tcp, tcp->u_arg[1]);
874                 tprintf(", %lu", tcp->u_arg[2]);
875         }
876         return 0;
877 }
878
879 int
880 osf_fstatfs(tcp)
881 struct tcb *tcp;
882 {
883         if (entering(tcp)) {
884                 tprintf("%lu, ", tcp->u_arg[0]);
885         } else {
886                 printstatfs(tcp, tcp->u_arg[1]);
887                 tprintf(", %lu", tcp->u_arg[2]);
888         }
889         return 0;
890 }
891 #endif /* linux && alpha */
892
893 #endif /* !SVR4 */
894
895 #ifdef SUNOS4
896
897 int
898 sys_ustat(tcp)
899 struct tcb *tcp;
900 {
901         struct ustat statbuf;
902
903         if (entering(tcp)) {
904                 tprintf("makedev(%lu, %lu), ",
905                                 (long) major(tcp->u_arg[0]),
906                                 (long) minor(tcp->u_arg[0]));
907         }
908         else {
909                 if (syserror(tcp) || !verbose(tcp))
910                         tprintf("%#lx", tcp->u_arg[1]);
911                 else if (umove(tcp, tcp->u_arg[1], &statbuf) < 0)
912                         tprintf("{...}");
913                 else {
914                         tprintf("{f_tfree=%lu, f_tinode=%lu, ",
915                                 statbuf.f_tfree, statbuf.f_tinode);
916                         tprintf("f_fname=\"%.*s\", ",
917                                 (int) sizeof(statbuf.f_fname),
918                                 statbuf.f_fname);
919                         tprintf("f_fpack=\"%.*s\"}",
920                                 (int) sizeof(statbuf.f_fpack),
921                                 statbuf.f_fpack);
922                 }
923         }
924         return 0;
925 }
926
927 #endif /* SUNOS4 */
928
929 /* directory */
930 int
931 sys_chdir(tcp)
932 struct tcb *tcp;
933 {
934         if (entering(tcp)) {
935                 printpath(tcp, tcp->u_arg[0]);
936         }
937         return 0;
938 }
939
940 int
941 sys_mkdir(tcp)
942 struct tcb *tcp;
943 {
944         if (entering(tcp)) {
945                 printpath(tcp, tcp->u_arg[0]);
946                 tprintf(", %#lo", tcp->u_arg[1]);
947         }
948         return 0;
949 }
950
951 int
952 sys_rmdir(tcp)
953 struct tcb *tcp;
954 {
955         if (entering(tcp)) {
956                 printpath(tcp, tcp->u_arg[0]);
957         }
958         return 0;
959 }
960
961 int
962 sys_fchdir(tcp)
963 struct tcb *tcp;
964 {
965         if (entering(tcp)) {
966                 tprintf("%ld", tcp->u_arg[0]);
967         }
968         return 0;
969 }
970
971 int
972 sys_chroot(tcp)
973 struct tcb *tcp;
974 {
975         if (entering(tcp)) {
976                 printpath(tcp, tcp->u_arg[0]);
977         }
978         return 0;
979 }
980
981 int
982 sys_fchroot(tcp)
983 struct tcb *tcp;
984 {
985         if (entering(tcp)) {
986                 tprintf("%ld", tcp->u_arg[0]);
987         }
988         return 0;
989 }
990
991 int
992 sys_link(tcp)
993 struct tcb *tcp;
994 {
995         if (entering(tcp)) {
996                 printpath(tcp, tcp->u_arg[0]);
997                 tprintf(", ");
998                 printpath(tcp, tcp->u_arg[1]);
999         }
1000         return 0;
1001 }
1002
1003 int
1004 sys_unlink(tcp)
1005 struct tcb *tcp;
1006 {
1007         if (entering(tcp)) {
1008                 printpath(tcp, tcp->u_arg[0]);
1009         }
1010         return 0;
1011 }
1012
1013 int
1014 sys_symlink(tcp)
1015 struct tcb *tcp;
1016 {
1017         if (entering(tcp)) {
1018                 printpath(tcp, tcp->u_arg[0]);
1019                 tprintf(", ");
1020                 printpath(tcp, tcp->u_arg[1]);
1021         }
1022         return 0;
1023 }
1024
1025 int
1026 sys_readlink(tcp)
1027 struct tcb *tcp;
1028 {
1029         if (entering(tcp)) {
1030                 printpath(tcp, tcp->u_arg[0]);
1031                 tprintf(", ");
1032         } else {
1033                 if (syserror(tcp))
1034                         tprintf("%#lx", tcp->u_arg[1]);
1035                 else
1036                         printpathn(tcp, tcp->u_arg[1], tcp->u_rval);
1037                 tprintf(", %lu", tcp->u_arg[2]);
1038         }
1039         return 0;
1040 }
1041
1042 int
1043 sys_rename(tcp)
1044 struct tcb *tcp;
1045 {
1046         if (entering(tcp)) {
1047                 printpath(tcp, tcp->u_arg[0]);
1048                 tprintf(", ");
1049                 printpath(tcp, tcp->u_arg[1]);
1050         }
1051         return 0;
1052 }
1053
1054 int
1055 sys_chown(tcp)
1056 struct tcb *tcp;
1057 {
1058         if (entering(tcp)) {
1059                 printpath(tcp, tcp->u_arg[0]);
1060                 tprintf(", %lu, %lu", tcp->u_arg[1], tcp->u_arg[2]);
1061         }
1062         return 0;
1063 }
1064
1065 int
1066 sys_fchown(tcp)
1067 struct tcb *tcp;
1068 {
1069         if (entering(tcp)) {
1070                 tprintf("%ld, %lu, %lu",
1071                         tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
1072         }
1073         return 0;
1074 }
1075
1076 int
1077 sys_chmod(tcp)
1078 struct tcb *tcp;
1079 {
1080         if (entering(tcp)) {
1081                 printpath(tcp, tcp->u_arg[0]);
1082                 tprintf(", %#lo", tcp->u_arg[1]);
1083         }
1084         return 0;
1085 }
1086
1087 int
1088 sys_fchmod(tcp)
1089 struct tcb *tcp;
1090 {
1091         if (entering(tcp)) {
1092                 tprintf("%ld, %#lo", tcp->u_arg[0], tcp->u_arg[1]);
1093         }
1094         return 0;
1095 }
1096
1097 int
1098 sys_utimes(tcp)
1099 struct tcb *tcp;
1100 {
1101         if (entering(tcp)) {
1102                 printpath(tcp, tcp->u_arg[0]);
1103                 tprintf(", ");
1104                 printtv(tcp, tcp->u_arg[1]);
1105         }
1106         return 0;
1107 }
1108
1109 int
1110 sys_utime(tcp)
1111 struct tcb *tcp;
1112 {
1113         long ut[2];
1114
1115         if (entering(tcp)) {
1116                 printpath(tcp, tcp->u_arg[0]);
1117                 tprintf(", ");
1118                 if (!tcp->u_arg[1])
1119                         tprintf("NULL");
1120                 else if (!verbose(tcp))
1121                         tprintf("%#lx", tcp->u_arg[1]);
1122                 else if (umoven(tcp, tcp->u_arg[1], sizeof ut,
1123                     (char *) ut) < 0)
1124                         tprintf("[?, ?]");
1125                 else {
1126                         tprintf("[%s,", sprinttime(ut[0]));
1127                         tprintf(" %s]", sprinttime(ut[1]));
1128                 }
1129         }
1130         return 0;
1131 }
1132
1133 int
1134 sys_mknod(tcp)
1135 struct tcb *tcp;
1136 {
1137         int mode = tcp->u_arg[1];
1138
1139         if (entering(tcp)) {
1140                 printpath(tcp, tcp->u_arg[0]);
1141                 tprintf(", %s", sprintmode(mode));
1142                 switch (mode & S_IFMT) {
1143                 case S_IFCHR: case S_IFBLK:
1144 #ifdef LINUXSPARC
1145                         if (current_personality == 1)
1146                         tprintf(", makedev(%lu, %lu)",
1147                                 (unsigned long) ((tcp->u_arg[2] >> 18) & 0x3fff),
1148                                 (unsigned long) (tcp->u_arg[2] & 0x3ffff));
1149                         else
1150 #endif  
1151                         tprintf(", makedev(%lu, %lu)",
1152                                 (unsigned long) major(tcp->u_arg[2]),
1153                                 (unsigned long) minor(tcp->u_arg[2]));
1154                         break;
1155                 default:
1156                         break;
1157                 }
1158         }
1159         return 0;
1160 }
1161
1162 int
1163 sys_mkfifo(tcp)
1164 struct tcb *tcp;
1165 {
1166         if (entering(tcp)) {
1167                 printpath(tcp, tcp->u_arg[0]);
1168                 tprintf(", %#lo", tcp->u_arg[1]);
1169         }
1170         return 0;
1171 }
1172
1173 int
1174 sys_fsync(tcp)
1175 struct tcb *tcp;
1176 {
1177         if (entering(tcp)) {
1178                 tprintf("%ld", tcp->u_arg[0]);
1179         }
1180         return 0;
1181 }
1182
1183 #ifdef linux
1184
1185 static void
1186 printdir(tcp, addr)
1187 struct tcb *tcp;
1188 long addr;
1189 {
1190         struct dirent d;
1191
1192         if (!verbose(tcp)) {
1193                 tprintf("%#lx", addr);
1194                 return;
1195         }
1196         if (umove(tcp, addr, &d) < 0) {
1197                 tprintf("{...}");
1198                 return;
1199         }
1200         tprintf("{d_ino=%ld, ", (unsigned long) d.d_ino);
1201         tprintf("d_name=");
1202         printpathn(tcp, (long) ((struct dirent *) addr)->d_name, d.d_reclen);
1203         tprintf("}");
1204 }
1205
1206 int
1207 sys_readdir(tcp)
1208 struct tcb *tcp;
1209 {
1210         if (entering(tcp)) {
1211                 tprintf("%lu, ", tcp->u_arg[0]);
1212         } else {
1213                 if (syserror(tcp) || tcp->u_rval == 0 || !verbose(tcp))
1214                         tprintf("%#lx", tcp->u_arg[1]);
1215                 else
1216                         printdir(tcp, tcp->u_arg[1]);
1217                 /* Not much point in printing this out, it is always 1. */
1218                 if (tcp->u_arg[2] != 1)
1219                         tprintf(", %lu", tcp->u_arg[2]);
1220         }
1221         return 0;
1222 }
1223
1224 #endif /* linux */
1225
1226 int
1227 sys_getdents(tcp)
1228 struct tcb *tcp;
1229 {
1230         int i, len, dents = 0;
1231         char *buf;
1232
1233         if (entering(tcp)) {
1234                 tprintf("%lu, ", tcp->u_arg[0]);
1235                 return 0;
1236         }
1237         if (syserror(tcp) || !verbose(tcp)) {
1238                 tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
1239                 return 0;
1240         }
1241 #ifdef linux
1242 #ifdef __sparc__
1243         tprintf (" = Unknown value\n");
1244         return 0;
1245 #endif
1246 #endif
1247         len = tcp->u_rval;
1248         if ((buf = malloc(len)) == NULL) {
1249                 tprintf("out of memory\n");
1250                 return 0;
1251         }
1252         if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
1253                 tprintf("{...}, %lu", tcp->u_arg[2]);
1254                 free(buf);
1255                 return 0;
1256         }
1257         if (!abbrev(tcp))
1258                 tprintf("{");
1259         for (i = 0; i < len;) {
1260                 struct dirent *d = (struct dirent *) &buf[i];
1261 #ifdef linux
1262                 if (!abbrev(tcp)) {
1263                         tprintf("%s{d_ino=%lu, d_off=%lu, ",
1264                                 i ? " " : "", d->d_ino, d->d_off);
1265                         tprintf("d_reclen=%u, d_name=\"%s\"}",
1266                                 d->d_reclen, d->d_name);
1267                 }
1268 #endif /* linux */
1269 #ifdef SVR4
1270                 if (!abbrev(tcp)) {
1271                         tprintf("%s{d_ino=%lu, d_off=%lu, ",
1272                                 i ? " " : "", d->d_ino, d->d_off);
1273                         tprintf("d_reclen=%u, d_name=\"%s\"}",
1274                                 d->d_reclen, d->d_name);
1275                 }
1276 #endif /* SVR4 */
1277 #ifdef SUNOS4
1278                 if (!abbrev(tcp)) {
1279                         tprintf("%s{d_off=%lu, d_fileno=%lu, d_reclen=%u, ",
1280                                 i ? " " : "", d->d_off, d->d_fileno,
1281                                 d->d_reclen);
1282                         tprintf("d_namlen=%u, d_name=\"%.*s\"}",
1283                                 d->d_namlen, d->d_namlen, d->d_name);
1284                 }
1285 #endif /* SUNOS4 */
1286                 i += d->d_reclen;
1287                 dents++;
1288         }
1289         if (!abbrev(tcp))
1290                 tprintf("}");
1291         else
1292                 tprintf("/* %u entries */", dents);
1293         tprintf(", %lu", tcp->u_arg[2]);
1294         free(buf);
1295         return 0;
1296 }
1297
1298 #ifdef linux
1299
1300 int
1301 sys_getcwd(tcp)
1302 struct tcb *tcp;
1303 {
1304     if (exiting(tcp)) {
1305         if (syserror(tcp))
1306             tprintf("%#lx", tcp->u_arg[0]);
1307         else
1308             printstr(tcp, tcp->u_arg[0], tcp->u_arg[1]);
1309         tprintf(", %lu", tcp->u_arg[1]);
1310     }
1311     return 0;
1312 }
1313 #endif /* linux */
1314
1315 #ifdef HAVE_SYS_ASYNCH_H
1316
1317 int
1318 sys_aioread(tcp)
1319 struct tcb *tcp;
1320 {
1321         struct aio_result_t res;
1322
1323         if (entering(tcp)) {
1324                 tprintf("%lu, ", tcp->u_arg[0]);
1325         } else {
1326                 if (syserror(tcp))
1327                         tprintf("%#lx", tcp->u_arg[1]);
1328                 else
1329                         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1330                 tprintf(", %lu, %lu, ", tcp->u_arg[2], tcp->u_arg[3]);
1331                 printxval(whence, tcp->u_arg[4], "L_???");
1332                 if (syserror(tcp) || tcp->u_arg[5] == 0
1333                     || umove(tcp, tcp->u_arg[5], &res) < 0)
1334                         tprintf(", %#lx", tcp->u_arg[5]);
1335                 else
1336                         tprintf(", {aio_return %d aio_errno %d}",
1337                                 res.aio_return, res.aio_errno);
1338         }
1339         return 0;
1340 }
1341
1342 int
1343 sys_aiowrite(tcp)
1344 struct tcb *tcp;
1345 {
1346         struct aio_result_t res;
1347
1348         if (entering(tcp)) {
1349                 tprintf("%lu, ", tcp->u_arg[0]);
1350                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1351                 tprintf(", %lu, %lu, ", tcp->u_arg[2], tcp->u_arg[3]);
1352                 printxval(whence, tcp->u_arg[4], "L_???");
1353         }
1354         else {
1355                 if (tcp->u_arg[5] == 0)
1356                         tprintf(", NULL");
1357                 else if (syserror(tcp)
1358                     || umove(tcp, tcp->u_arg[5], &res) < 0)
1359                         tprintf(", %#lx", tcp->u_arg[5]);
1360                 else
1361                         tprintf(", {aio_return %d aio_errno %d}",
1362                                 res.aio_return, res.aio_errno);
1363         }
1364         return 0;
1365 }
1366
1367 int
1368 sys_aiowait(tcp)
1369 struct tcb *tcp;
1370 {
1371         if (entering(tcp))
1372                 printtv(tcp, tcp->u_arg[0]);
1373         return 0;
1374 }
1375
1376 int
1377 sys_aiocancel(tcp)
1378 struct tcb *tcp;
1379 {
1380         struct aio_result_t res;
1381
1382         if (exiting(tcp)) {
1383                 if (tcp->u_arg[0] == 0)
1384                         tprintf("NULL");
1385                 else if (syserror(tcp)
1386                     || umove(tcp, tcp->u_arg[0], &res) < 0)
1387                         tprintf("%#lx", tcp->u_arg[0]);
1388                 else
1389                         tprintf("{aio_return %d aio_errno %d}",
1390                                 res.aio_return, res.aio_errno);
1391         }
1392         return 0;
1393 }
1394
1395 #endif /* HAVE_SYS_ASYNCH_H */