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