]> granicus.if.org Git - strace/blob - file.c
Cleanup struct stat.st_flags decoding
[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  * 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
31 #include "defs.h"
32
33 #if defined(SPARC) || defined(SPARC64)
34 struct stat {
35         unsigned short  st_dev;
36         unsigned int    st_ino;
37         unsigned short  st_mode;
38         short           st_nlink;
39         unsigned short  st_uid;
40         unsigned short  st_gid;
41         unsigned short  st_rdev;
42         unsigned int    st_size;
43         int             st_atime;
44         unsigned int    __unused1;
45         int             st_mtime;
46         unsigned int    __unused2;
47         int             st_ctime;
48         unsigned int    __unused3;
49         int             st_blksize;
50         int             st_blocks;
51         unsigned int    __unused4[2];
52 };
53 # if defined(SPARC64)
54 struct stat_sparc64 {
55         unsigned int    st_dev;
56         unsigned long   st_ino;
57         unsigned int    st_mode;
58         unsigned int    st_nlink;
59         unsigned int    st_uid;
60         unsigned int    st_gid;
61         unsigned int    st_rdev;
62         long            st_size;
63         long            st_atime;
64         long            st_mtime;
65         long            st_ctime;
66         long            st_blksize;
67         long            st_blocks;
68         unsigned long   __unused4[2];
69 };
70 # endif /* SPARC64 */
71 # define stat kernel_stat
72 # include <asm/stat.h>
73 # undef stat
74 #elif defined(X32)
75 struct stat {
76         unsigned long long      st_dev;
77         unsigned long long      st_ino;
78         unsigned long long      st_nlink;
79
80         unsigned int            st_mode;
81         unsigned int            st_uid;
82         unsigned int            st_gid;
83         unsigned int            __pad0;
84         unsigned long long      st_rdev;
85         long long               st_size;
86         long long               st_blksize;
87         long long               st_blocks;
88
89         unsigned long long      st_atime;
90         unsigned long long      st_atime_nsec;
91         unsigned long long      st_mtime;
92         unsigned long long      st_mtime_nsec;
93         unsigned long long      st_ctime;
94         unsigned long long      st_ctime_nsec;
95         long long               __unused[3];
96 };
97
98 struct stat64 {
99         unsigned long long      st_dev;
100         unsigned char           __pad0[4];
101         unsigned long           __st_ino;
102         unsigned int            st_mode;
103         unsigned int            st_nlink;
104         unsigned long           st_uid;
105         unsigned long           st_gid;
106         unsigned long long      st_rdev;
107         unsigned char           __pad3[4];
108         long long               st_size;
109         unsigned long           st_blksize;
110         unsigned long long      st_blocks;
111         unsigned long           st_atime;
112         unsigned long           st_atime_nsec;
113         unsigned long           st_mtime;
114         unsigned int            st_mtime_nsec;
115         unsigned long           st_ctime;
116         unsigned long           st_ctime_nsec;
117         unsigned long long      st_ino;
118 } __attribute__((packed));
119 # define HAVE_STAT64    1
120
121 struct __old_kernel_stat {
122         unsigned short st_dev;
123         unsigned short st_ino;
124         unsigned short st_mode;
125         unsigned short st_nlink;
126         unsigned short st_uid;
127         unsigned short st_gid;
128         unsigned short st_rdev;
129         unsigned int   st_size;
130         unsigned int   st_atime;
131         unsigned int   st_mtime;
132         unsigned int   st_ctime;
133 };
134 #else
135 # undef dev_t
136 # undef ino_t
137 # undef mode_t
138 # undef nlink_t
139 # undef uid_t
140 # undef gid_t
141 # undef off_t
142 # undef loff_t
143 # define dev_t __kernel_dev_t
144 # define ino_t __kernel_ino_t
145 # define mode_t __kernel_mode_t
146 # define nlink_t __kernel_nlink_t
147 # define uid_t __kernel_uid_t
148 # define gid_t __kernel_gid_t
149 # define off_t __kernel_off_t
150 # define loff_t __kernel_loff_t
151
152 # include <asm/stat.h>
153
154 # undef dev_t
155 # undef ino_t
156 # undef mode_t
157 # undef nlink_t
158 # undef uid_t
159 # undef gid_t
160 # undef off_t
161 # undef loff_t
162 # define dev_t dev_t
163 # define ino_t ino_t
164 # define mode_t mode_t
165 # define nlink_t nlink_t
166 # define uid_t uid_t
167 # define gid_t gid_t
168 # define off_t off_t
169 # define loff_t loff_t
170 #endif
171
172 #define stat libc_stat
173 #define stat64 libc_stat64
174 #include <sys/stat.h>
175 #undef stat
176 #undef stat64
177 /* These might be macros. */
178 #undef st_atime
179 #undef st_mtime
180 #undef st_ctime
181
182 #ifdef MAJOR_IN_SYSMACROS
183 # include <sys/sysmacros.h>
184 #endif
185
186 #ifdef MAJOR_IN_MKDEV
187 # include <sys/mkdev.h>
188 #endif
189
190 /* several stats */
191
192 #if defined(SPARC) || defined(SPARC64)
193 typedef struct {
194         int     tv_sec;
195         int     tv_nsec;
196 } timestruct_t;
197
198 struct solstat {
199         unsigned        st_dev;
200         int             st_pad1[3];     /* network id */
201         unsigned        st_ino;
202         unsigned        st_mode;
203         unsigned        st_nlink;
204         unsigned        st_uid;
205         unsigned        st_gid;
206         unsigned        st_rdev;
207         int             st_pad2[2];
208         int             st_size;
209         int             st_pad3;        /* st_size, off_t expansion */
210         timestruct_t    st_atime;
211         timestruct_t    st_mtime;
212         timestruct_t    st_ctime;
213         int             st_blksize;
214         int             st_blocks;
215         char            st_fstype[16];
216         int             st_pad4[8];     /* expansion area */
217 };
218
219 static void
220 printstatsol(struct tcb *tcp, long addr)
221 {
222         struct solstat statbuf;
223
224         if (umove(tcp, addr, &statbuf) < 0) {
225                 tprints("{...}");
226                 return;
227         }
228         if (!abbrev(tcp)) {
229                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
230                         (unsigned long) ((statbuf.st_dev >> 18) & 0x3fff),
231                         (unsigned long) (statbuf.st_dev & 0x3ffff),
232                         (unsigned long) statbuf.st_ino,
233                         sprintmode(statbuf.st_mode));
234                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
235                         (unsigned long) statbuf.st_nlink,
236                         (unsigned long) statbuf.st_uid,
237                         (unsigned long) statbuf.st_gid);
238                 tprintf("st_blksize=%lu, ", (unsigned long) statbuf.st_blksize);
239                 tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
240         }
241         else
242                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
243         switch (statbuf.st_mode & S_IFMT) {
244         case S_IFCHR: case S_IFBLK:
245                 tprintf("st_rdev=makedev(%lu, %lu), ",
246                         (unsigned long) ((statbuf.st_rdev >> 18) & 0x3fff),
247                         (unsigned long) (statbuf.st_rdev & 0x3ffff));
248                 break;
249         default:
250                 tprintf("st_size=%u, ", statbuf.st_size);
251                 break;
252         }
253         if (!abbrev(tcp)) {
254                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime.tv_sec));
255                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime.tv_sec));
256                 tprintf("st_ctime=%s}", sprinttime(statbuf.st_ctime.tv_sec));
257         }
258         else
259                 tprints("...}");
260 }
261
262 # if defined(SPARC64)
263 static void
264 printstat_sparc64(struct tcb *tcp, long addr)
265 {
266         struct stat_sparc64 statbuf;
267
268         if (umove(tcp, addr, &statbuf) < 0) {
269                 tprints("{...}");
270                 return;
271         }
272
273         if (!abbrev(tcp)) {
274                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
275                         (unsigned long) major(statbuf.st_dev),
276                         (unsigned long) minor(statbuf.st_dev),
277                         (unsigned long) statbuf.st_ino,
278                         sprintmode(statbuf.st_mode));
279                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
280                         (unsigned long) statbuf.st_nlink,
281                         (unsigned long) statbuf.st_uid,
282                         (unsigned long) statbuf.st_gid);
283                 tprintf("st_blksize=%lu, ",
284                         (unsigned long) statbuf.st_blksize);
285                 tprintf("st_blocks=%lu, ",
286                         (unsigned long) statbuf.st_blocks);
287         }
288         else
289                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
290         switch (statbuf.st_mode & S_IFMT) {
291         case S_IFCHR: case S_IFBLK:
292                 tprintf("st_rdev=makedev(%lu, %lu), ",
293                         (unsigned long) major(statbuf.st_rdev),
294                         (unsigned long) minor(statbuf.st_rdev));
295                 break;
296         default:
297                 tprintf("st_size=%lu, ", statbuf.st_size);
298                 break;
299         }
300         if (!abbrev(tcp)) {
301                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
302                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
303                 tprintf("st_ctime=%s}", sprinttime(statbuf.st_ctime));
304         }
305         else
306                 tprints("...}");
307 }
308 # endif /* SPARC64 */
309 #endif /* SPARC[64] */
310
311 #if defined POWERPC64
312 struct stat_powerpc32 {
313         unsigned int    st_dev;
314         unsigned int    st_ino;
315         unsigned int    st_mode;
316         unsigned short  st_nlink;
317         unsigned int    st_uid;
318         unsigned int    st_gid;
319         unsigned int    st_rdev;
320         unsigned int    st_size;
321         unsigned int    st_blksize;
322         unsigned int    st_blocks;
323         unsigned int    st_atime;
324         unsigned int    st_atime_nsec;
325         unsigned int    st_mtime;
326         unsigned int    st_mtime_nsec;
327         unsigned int    st_ctime;
328         unsigned int    st_ctime_nsec;
329         unsigned int    __unused4;
330         unsigned int    __unused5;
331 };
332
333 static void
334 printstat_powerpc32(struct tcb *tcp, long addr)
335 {
336         struct stat_powerpc32 statbuf;
337
338         if (umove(tcp, addr, &statbuf) < 0) {
339                 tprints("{...}");
340                 return;
341         }
342
343         if (!abbrev(tcp)) {
344                 tprintf("{st_dev=makedev(%u, %u), st_ino=%u, st_mode=%s, ",
345                         major(statbuf.st_dev), minor(statbuf.st_dev),
346                         statbuf.st_ino,
347                         sprintmode(statbuf.st_mode));
348                 tprintf("st_nlink=%u, st_uid=%u, st_gid=%u, ",
349                         statbuf.st_nlink, statbuf.st_uid, statbuf.st_gid);
350                 tprintf("st_blksize=%u, ", statbuf.st_blksize);
351                 tprintf("st_blocks=%u, ", statbuf.st_blocks);
352         }
353         else
354                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
355         switch (statbuf.st_mode & S_IFMT) {
356         case S_IFCHR: case S_IFBLK:
357                 tprintf("st_rdev=makedev(%lu, %lu), ",
358                         (unsigned long) major(statbuf.st_rdev),
359                         (unsigned long) minor(statbuf.st_rdev));
360                 break;
361         default:
362                 tprintf("st_size=%u, ", statbuf.st_size);
363                 break;
364         }
365         if (!abbrev(tcp)) {
366                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
367                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
368                 tprintf("st_ctime=%s}", sprinttime(statbuf.st_ctime));
369         }
370         else
371                 tprints("...}");
372 }
373 #endif /* POWERPC64 */
374
375 static void
376 realprintstat(struct tcb *tcp, struct stat *statbuf)
377 {
378         if (!abbrev(tcp)) {
379                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
380                         (unsigned long) major(statbuf->st_dev),
381                         (unsigned long) minor(statbuf->st_dev),
382                         (unsigned long) statbuf->st_ino,
383                         sprintmode(statbuf->st_mode));
384                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
385                         (unsigned long) statbuf->st_nlink,
386                         (unsigned long) statbuf->st_uid,
387                         (unsigned long) statbuf->st_gid);
388 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
389                 tprintf("st_blksize=%lu, ", (unsigned long) statbuf->st_blksize);
390 #endif
391 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
392                 tprintf("st_blocks=%lu, ", (unsigned long) statbuf->st_blocks);
393 #endif
394         }
395         else
396                 tprintf("{st_mode=%s, ", sprintmode(statbuf->st_mode));
397         switch (statbuf->st_mode & S_IFMT) {
398         case S_IFCHR: case S_IFBLK:
399 #ifdef HAVE_STRUCT_STAT_ST_RDEV
400                 tprintf("st_rdev=makedev(%lu, %lu), ",
401                         (unsigned long) major(statbuf->st_rdev),
402                         (unsigned long) minor(statbuf->st_rdev));
403 #else /* !HAVE_STRUCT_STAT_ST_RDEV */
404                 tprintf("st_size=makedev(%lu, %lu), ",
405                         (unsigned long) major(statbuf->st_size),
406                         (unsigned long) minor(statbuf->st_size));
407 #endif /* !HAVE_STRUCT_STAT_ST_RDEV */
408                 break;
409         default:
410                 tprintf("st_size=%lu, ", (unsigned long) statbuf->st_size);
411                 break;
412         }
413         if (!abbrev(tcp)) {
414                 tprintf("st_atime=%s, ", sprinttime(statbuf->st_atime));
415                 tprintf("st_mtime=%s, ", sprinttime(statbuf->st_mtime));
416                 tprintf("st_ctime=%s", sprinttime(statbuf->st_ctime));
417 #if HAVE_STRUCT_STAT_ST_FLAGS
418                 tprintf(", st_flags=%u", statbuf->st_flags);
419 #endif
420 #if HAVE_STRUCT_STAT_ST_FSTYPE
421                 tprintf(", st_fstype=%.*s",
422                         (int) sizeof statbuf->st_fstype, statbuf->st_fstype);
423 #endif
424 #if HAVE_STRUCT_STAT_ST_GEN
425                 tprintf(", st_gen=%u", statbuf->st_gen);
426 #endif
427                 tprints("}");
428         }
429         else
430                 tprints("...}");
431 }
432
433 #ifndef X32
434 static void
435 printstat(struct tcb *tcp, long addr)
436 {
437         struct stat statbuf;
438
439         if (!addr) {
440                 tprints("NULL");
441                 return;
442         }
443         if (syserror(tcp) || !verbose(tcp)) {
444                 tprintf("%#lx", addr);
445                 return;
446         }
447
448 #if defined(SPARC) || defined(SPARC64)
449         if (current_personality == 1) {
450                 printstatsol(tcp, addr);
451                 return;
452         }
453 #ifdef SPARC64
454         else if (current_personality == 2) {
455                 printstat_sparc64(tcp, addr);
456                 return;
457         }
458 #endif
459 #endif /* SPARC[64] */
460
461 #if defined POWERPC64
462         if (current_personality == 1) {
463                 printstat_powerpc32(tcp, addr);
464                 return;
465         }
466 #endif
467
468         if (umove(tcp, addr, &statbuf) < 0) {
469                 tprints("{...}");
470                 return;
471         }
472
473         realprintstat(tcp, &statbuf);
474 }
475 #else /* X32 */
476 # define printstat printstat64
477 #endif
478
479 #if !defined HAVE_STAT64 && (defined AARCH64 || defined X86_64)
480 /*
481  * Linux x86_64 has unified `struct stat' but its i386 biarch needs
482  * `struct stat64'.  Its <asm-i386/stat.h> definition expects 32-bit `long'.
483  * <linux/include/asm-x86_64/ia32.h> is not in the public includes set.
484  * __GNUC__ is needed for the required __attribute__ below.
485  *
486  * Similarly, aarch64 has a unified `struct stat' but its arm personality
487  * needs `struct stat64' (which also expects a 32-bit `long' but which
488  * shouldn't be packed).
489  */
490 struct stat64 {
491         unsigned long long      st_dev;
492         unsigned char   __pad0[4];
493         unsigned int    __st_ino;
494         unsigned int    st_mode;
495         unsigned int    st_nlink;
496         unsigned int    st_uid;
497         unsigned int    st_gid;
498         unsigned long long      st_rdev;
499         unsigned char   __pad3[4];
500         long long       st_size;
501         unsigned int    st_blksize;
502         unsigned long long      st_blocks;
503         unsigned int    st_atime;
504         unsigned int    st_atime_nsec;
505         unsigned int    st_mtime;
506         unsigned int    st_mtime_nsec;
507         unsigned int    st_ctime;
508         unsigned int    st_ctime_nsec;
509         unsigned long long      st_ino;
510 }
511 # if defined X86_64
512    __attribute__((packed))
513 #  define STAT64_SIZE   96
514 #else
515 #  define STAT64_SIZE   104
516 # endif
517 ;
518 # define HAVE_STAT64    1
519 #endif
520
521 #ifdef HAVE_STAT64
522 static void
523 printstat64(struct tcb *tcp, long addr)
524 {
525 #ifdef X32
526         struct stat statbuf;
527 #else
528         struct stat64 statbuf;
529 #endif
530
531 #ifdef STAT64_SIZE
532         (void) sizeof(char[sizeof statbuf == STAT64_SIZE ? 1 : -1]);
533 #endif
534
535         if (!addr) {
536                 tprints("NULL");
537                 return;
538         }
539         if (syserror(tcp) || !verbose(tcp)) {
540                 tprintf("%#lx", addr);
541                 return;
542         }
543
544 #if defined(SPARC) || defined(SPARC64)
545         if (current_personality == 1) {
546                 printstatsol(tcp, addr);
547                 return;
548         }
549 # ifdef SPARC64
550         else if (current_personality == 2) {
551                 printstat_sparc64(tcp, addr);
552                 return;
553         }
554 # endif
555 #endif /* SPARC[64] */
556
557 #if defined AARCH64
558         if (current_personality != 0) {
559                 printstat(tcp, addr);
560                 return;
561         }
562 #endif
563 #if defined X86_64
564         if (current_personality != 1) {
565                 printstat(tcp, addr);
566                 return;
567         }
568 #endif
569
570         if (umove(tcp, addr, &statbuf) < 0) {
571                 tprints("{...}");
572                 return;
573         }
574
575         if (!abbrev(tcp)) {
576                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%llu, st_mode=%s, ",
577                         (unsigned long) major(statbuf.st_dev),
578                         (unsigned long) minor(statbuf.st_dev),
579                         (unsigned long long) statbuf.st_ino,
580                         sprintmode(statbuf.st_mode));
581                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
582                         (unsigned long) statbuf.st_nlink,
583                         (unsigned long) statbuf.st_uid,
584                         (unsigned long) statbuf.st_gid);
585 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
586                 tprintf("st_blksize=%lu, ",
587                         (unsigned long) statbuf.st_blksize);
588 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
589 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
590                 tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
591 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
592         }
593         else
594                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
595         switch (statbuf.st_mode & S_IFMT) {
596         case S_IFCHR: case S_IFBLK:
597 #ifdef HAVE_STRUCT_STAT_ST_RDEV
598                 tprintf("st_rdev=makedev(%lu, %lu), ",
599                         (unsigned long) major(statbuf.st_rdev),
600                         (unsigned long) minor(statbuf.st_rdev));
601 #else /* !HAVE_STRUCT_STAT_ST_RDEV */
602                 tprintf("st_size=makedev(%lu, %lu), ",
603                         (unsigned long) major(statbuf.st_size),
604                         (unsigned long) minor(statbuf.st_size));
605 #endif /* !HAVE_STRUCT_STAT_ST_RDEV */
606                 break;
607         default:
608                 tprintf("st_size=%llu, ", (unsigned long long) statbuf.st_size);
609                 break;
610         }
611         if (!abbrev(tcp)) {
612                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
613                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
614                 tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
615 #if HAVE_STRUCT_STAT_ST_FLAGS
616                 tprintf(", st_flags=%u", statbuf->st_flags);
617 #endif
618 #if HAVE_STRUCT_STAT_ST_FSTYPE
619                 tprintf(", st_fstype=%.*s",
620                         (int) sizeof statbuf.st_fstype, statbuf.st_fstype);
621 #endif
622 #if HAVE_STRUCT_STAT_ST_GEN
623                 tprintf(", st_gen=%u", statbuf.st_gen);
624 #endif
625                 tprints("}");
626         }
627         else
628                 tprints("...}");
629 }
630 #endif /* HAVE_STAT64 */
631
632 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
633 static void
634 convertoldstat(const struct __old_kernel_stat *oldbuf, struct stat *newbuf)
635 {
636         newbuf->st_dev = oldbuf->st_dev;
637         newbuf->st_ino = oldbuf->st_ino;
638         newbuf->st_mode = oldbuf->st_mode;
639         newbuf->st_nlink = oldbuf->st_nlink;
640         newbuf->st_uid = oldbuf->st_uid;
641         newbuf->st_gid = oldbuf->st_gid;
642         newbuf->st_rdev = oldbuf->st_rdev;
643         newbuf->st_size = oldbuf->st_size;
644         newbuf->st_atime = oldbuf->st_atime;
645         newbuf->st_mtime = oldbuf->st_mtime;
646         newbuf->st_ctime = oldbuf->st_ctime;
647         newbuf->st_blksize = 0; /* not supported in old_stat */
648         newbuf->st_blocks = 0; /* not supported in old_stat */
649 }
650
651 static void
652 printoldstat(struct tcb *tcp, long addr)
653 {
654         struct __old_kernel_stat statbuf;
655         struct stat newstatbuf;
656
657         if (!addr) {
658                 tprints("NULL");
659                 return;
660         }
661         if (syserror(tcp) || !verbose(tcp)) {
662                 tprintf("%#lx", addr);
663                 return;
664         }
665
666 # if defined(SPARC) || defined(SPARC64)
667         if (current_personality == 1) {
668                 printstatsol(tcp, addr);
669                 return;
670         }
671 # endif
672
673         if (umove(tcp, addr, &statbuf) < 0) {
674                 tprints("{...}");
675                 return;
676         }
677
678         convertoldstat(&statbuf, &newstatbuf);
679         realprintstat(tcp, &newstatbuf);
680 }
681 #endif
682
683 int
684 sys_stat(struct tcb *tcp)
685 {
686         if (entering(tcp)) {
687                 printpath(tcp, tcp->u_arg[0]);
688                 tprints(", ");
689         } else {
690                 printstat(tcp, tcp->u_arg[1]);
691         }
692         return 0;
693 }
694
695 #ifdef X32
696 static void
697 printstat64_x32(struct tcb *tcp, long addr)
698 {
699         struct stat64 statbuf;
700
701         if (!addr) {
702                 tprints("NULL");
703                 return;
704         }
705         if (syserror(tcp) || !verbose(tcp)) {
706                 tprintf("%#lx", addr);
707                 return;
708         }
709
710         if (umove(tcp, addr, &statbuf) < 0) {
711                 tprints("{...}");
712                 return;
713         }
714
715         if (!abbrev(tcp)) {
716                 tprintf("{st_dev=makedev(%lu, %lu), st_ino=%llu, st_mode=%s, ",
717                         (unsigned long) major(statbuf.st_dev),
718                         (unsigned long) minor(statbuf.st_dev),
719                         (unsigned long long) statbuf.st_ino,
720                         sprintmode(statbuf.st_mode));
721                 tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
722                         (unsigned long) statbuf.st_nlink,
723                         (unsigned long) statbuf.st_uid,
724                         (unsigned long) statbuf.st_gid);
725                 tprintf("st_blksize=%lu, ",
726                         (unsigned long) statbuf.st_blksize);
727                 tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
728         }
729         else
730                 tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
731         switch (statbuf.st_mode & S_IFMT) {
732         case S_IFCHR: case S_IFBLK:
733                 tprintf("st_rdev=makedev(%lu, %lu), ",
734                         (unsigned long) major(statbuf.st_rdev),
735                         (unsigned long) minor(statbuf.st_rdev));
736                 break;
737         default:
738                 tprintf("st_size=%llu, ", (unsigned long long) statbuf.st_size);
739                 break;
740         }
741         if (!abbrev(tcp)) {
742                 tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
743                 tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
744                 tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
745                 tprints("}");
746         }
747         else
748                 tprints("...}");
749 }
750 #endif /* X32 */
751
752 int
753 sys_stat64(struct tcb *tcp)
754 {
755 #ifdef HAVE_STAT64
756         if (entering(tcp)) {
757                 printpath(tcp, tcp->u_arg[0]);
758                 tprints(", ");
759         } else {
760 # ifdef X32
761                 printstat64_x32(tcp, tcp->u_arg[1]);
762 # else
763                 printstat64(tcp, tcp->u_arg[1]);
764 # endif
765         }
766         return 0;
767 #else
768         return printargs(tcp);
769 #endif
770 }
771
772 int
773 sys_newfstatat(struct tcb *tcp)
774 {
775         if (entering(tcp)) {
776                 print_dirfd(tcp, tcp->u_arg[0]);
777                 printpath(tcp, tcp->u_arg[1]);
778                 tprints(", ");
779         } else {
780 #ifdef POWERPC64
781                 if (current_personality == 0)
782                         printstat(tcp, tcp->u_arg[2]);
783                 else
784                         printstat64(tcp, tcp->u_arg[2]);
785 #elif defined HAVE_STAT64
786                 printstat64(tcp, tcp->u_arg[2]);
787 #else
788                 printstat(tcp, tcp->u_arg[2]);
789 #endif
790                 tprints(", ");
791                 printflags(at_flags, tcp->u_arg[3], "AT_???");
792         }
793         return 0;
794 }
795
796 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
797 int
798 sys_oldstat(struct tcb *tcp)
799 {
800         if (entering(tcp)) {
801                 printpath(tcp, tcp->u_arg[0]);
802                 tprints(", ");
803         } else {
804                 printoldstat(tcp, tcp->u_arg[1]);
805         }
806         return 0;
807 }
808 #endif
809
810 int
811 sys_fstat(struct tcb *tcp)
812 {
813         if (entering(tcp)) {
814                 printfd(tcp, tcp->u_arg[0]);
815                 tprints(", ");
816         } else {
817                 printstat(tcp, tcp->u_arg[1]);
818         }
819         return 0;
820 }
821
822 int
823 sys_fstat64(struct tcb *tcp)
824 {
825 #ifdef HAVE_STAT64
826         if (entering(tcp)) {
827                 printfd(tcp, tcp->u_arg[0]);
828                 tprints(", ");
829         } else {
830 # ifdef X32
831                 printstat64_x32(tcp, tcp->u_arg[1]);
832 # else
833                 printstat64(tcp, tcp->u_arg[1]);
834 # endif
835         }
836         return 0;
837 #else
838         return printargs(tcp);
839 #endif
840 }
841
842 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
843 int
844 sys_oldfstat(struct tcb *tcp)
845 {
846         if (entering(tcp)) {
847                 printfd(tcp, tcp->u_arg[0]);
848                 tprints(", ");
849         } else {
850                 printoldstat(tcp, tcp->u_arg[1]);
851         }
852         return 0;
853 }
854 #endif
855
856 #if defined(SPARC) || defined(SPARC64)
857
858 int
859 sys_xstat(struct tcb *tcp)
860 {
861         if (entering(tcp)) {
862                 tprintf("%ld, ", tcp->u_arg[0]);
863                 printpath(tcp, tcp->u_arg[1]);
864                 tprints(", ");
865         } else {
866                 printstat(tcp, tcp->u_arg[2]);
867         }
868         return 0;
869 }
870
871 int
872 sys_fxstat(struct tcb *tcp)
873 {
874         if (entering(tcp)) {
875                 tprintf("%ld, ", tcp->u_arg[0]);
876                 printfd(tcp, tcp->u_arg[1]);
877                 tprints(", ");
878         } else {
879                 printstat(tcp, tcp->u_arg[2]);
880         }
881         return 0;
882 }
883
884 #endif /* SPARC || SPARC64 */