]> granicus.if.org Git - strace/blob - file.c
Print nanoseconds along with seconds in stat family syscalls
[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 #undef dev_t
34 #undef ino_t
35 #undef mode_t
36 #undef nlink_t
37 #undef uid_t
38 #undef gid_t
39 #undef off_t
40 #undef loff_t
41 #define dev_t __kernel_dev_t
42 #define ino_t __kernel_ino_t
43 #define mode_t __kernel_mode_t
44 #define nlink_t __kernel_nlink_t
45 #define uid_t __kernel_uid_t
46 #define gid_t __kernel_gid_t
47 #define off_t __kernel_off_t
48 #define loff_t __kernel_loff_t
49
50 #include <asm/stat.h>
51
52 #undef dev_t
53 #undef ino_t
54 #undef mode_t
55 #undef nlink_t
56 #undef uid_t
57 #undef gid_t
58 #undef off_t
59 #undef loff_t
60 #define dev_t dev_t
61 #define ino_t ino_t
62 #define mode_t mode_t
63 #define nlink_t nlink_t
64 #define uid_t uid_t
65 #define gid_t gid_t
66 #define off_t off_t
67 #define loff_t loff_t
68
69 /* for S_IFMT */
70 #define stat libc_stat
71 #define stat64 libc_stat64
72 #include <sys/stat.h>
73 #undef stat
74 #undef stat64
75 /* These might be macros. */
76 #undef st_atime
77 #undef st_mtime
78 #undef st_ctime
79
80 #if defined MAJOR_IN_SYSMACROS
81 # include <sys/sysmacros.h>
82 #elif defined MAJOR_IN_MKDEV
83 # include <sys/mkdev.h>
84 #endif
85
86 /* several stats */
87
88 #include "printstat.h"
89
90 /* all locally defined structures provide these fields */
91 #undef HAVE_STRUCT_STAT_ST_ATIME_NSEC
92 #define HAVE_STRUCT_STAT_ST_ATIME_NSEC 1
93 #undef HAVE_STRUCT_STAT_ST_CTIME_NSEC
94 #define HAVE_STRUCT_STAT_ST_CTIME_NSEC 1
95 #undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
96 #define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
97
98 #undef STAT32_PERSONALITY
99 #if SUPPORTED_PERSONALITIES > 1
100 # if defined AARCH64 || defined X86_64 || defined X32
101 struct stat32 {
102         unsigned int    st_dev;
103         unsigned int    st_ino;
104         unsigned short  st_mode;
105         unsigned short  st_nlink;
106         unsigned short  st_uid;
107         unsigned short  st_gid;
108         unsigned int    st_rdev;
109         unsigned int    st_size;
110         unsigned int    st_blksize;
111         unsigned int    st_blocks;
112         unsigned int    st_atime;
113         unsigned int    st_atime_nsec;
114         unsigned int    st_mtime;
115         unsigned int    st_mtime_nsec;
116         unsigned int    st_ctime;
117         unsigned int    st_ctime_nsec;
118         unsigned int    __unused4;
119         unsigned int    __unused5;
120 };
121 #  ifdef AARCH64
122 #   define STAT32_PERSONALITY 0
123 #  else
124 #   define STAT32_PERSONALITY 1
125 #  endif
126 # elif defined POWERPC64
127 struct stat32 {
128         unsigned int    st_dev;
129         unsigned int    st_ino;
130         unsigned int    st_mode;
131         unsigned short  st_nlink;
132         unsigned int    st_uid;
133         unsigned int    st_gid;
134         unsigned int    st_rdev;
135         unsigned int    st_size;
136         unsigned int    st_blksize;
137         unsigned int    st_blocks;
138         unsigned int    st_atime;
139         unsigned int    st_atime_nsec;
140         unsigned int    st_mtime;
141         unsigned int    st_mtime_nsec;
142         unsigned int    st_ctime;
143         unsigned int    st_ctime_nsec;
144         unsigned int    __unused4;
145         unsigned int    __unused5;
146 };
147 #  define STAT32_PERSONALITY 1
148 # elif defined SPARC64
149 struct stat32 {
150         unsigned short  st_dev;
151         unsigned int    st_ino;
152         unsigned short  st_mode;
153         unsigned short  st_nlink;
154         unsigned short  st_uid;
155         unsigned short  st_gid;
156         unsigned short  st_rdev;
157         unsigned int    st_size;
158         unsigned int    st_atime;
159         unsigned int    st_atime_nsec;
160         unsigned int    st_mtime;
161         unsigned int    st_mtime_nsec;
162         unsigned int    st_ctime;
163         unsigned int    st_ctime_nsec;
164         unsigned int    st_blksize;
165         unsigned int    st_blocks;
166         unsigned int    __unused4[2];
167 };
168 #  define STAT32_PERSONALITY 0
169 # elif defined SPARC
170 #  /* no 64-bit personalities */
171 # elif defined TILE
172 #  /* no 32-bit stat */
173 # else
174 #  warning FIXME: check whether struct stat32 definition is needed for this architecture!
175 # endif /* X86_64 || X32 || POWERPC64 */
176 #endif /* SUPPORTED_PERSONALITIES > 1 */
177
178 #ifdef STAT32_PERSONALITY
179 # define DO_PRINTSTAT do_printstat32
180 # define STRUCT_STAT struct stat32
181 # undef HAVE_STRUCT_STAT_ST_FLAGS
182 # undef HAVE_STRUCT_STAT_ST_FSTYPE
183 # undef HAVE_STRUCT_STAT_ST_GEN
184 # include "printstat.h"
185 #endif /* STAT32_PERSONALITY */
186
187 #if defined(SPARC) || defined(SPARC64)
188
189 struct solstat {
190         unsigned        st_dev;
191         unsigned int    st_pad1[3];     /* network id */
192         unsigned        st_ino;
193         unsigned        st_mode;
194         unsigned        st_nlink;
195         unsigned        st_uid;
196         unsigned        st_gid;
197         unsigned        st_rdev;
198         unsigned int    st_pad2[2];
199         unsigned int    st_size;
200         unsigned int    st_pad3;        /* st_size, off_t expansion */
201         unsigned int    st_atime;
202         unsigned int    st_atime_nsec;
203         unsigned int    st_mtime;
204         unsigned int    st_mtime_nsec;
205         unsigned int    st_ctime;
206         unsigned int    st_ctime_nsec;
207         unsigned int    st_blksize;
208         unsigned int    st_blocks;
209         char            st_fstype[16];
210         unsigned int    st_pad4[8];     /* expansion area */
211 };
212
213 # define DO_PRINTSTAT   do_printstat_sol
214 # define STRUCT_STAT    struct solstat
215 # define STAT_MAJOR(x)  (((x) >> 18) & 0x3fff)
216 # define STAT_MINOR(x)  ((x) & 0x3ffff)
217 # undef HAVE_STRUCT_STAT_ST_FLAGS
218 # undef HAVE_STRUCT_STAT_ST_FSTYPE
219 # undef HAVE_STRUCT_STAT_ST_GEN
220 # include "printstat.h"
221 #endif /* SPARC || SPARC64 */
222
223 static void
224 printstat(struct tcb *tcp, long addr)
225 {
226         struct stat statbuf;
227
228 #ifdef STAT32_PERSONALITY
229         if (current_personality == STAT32_PERSONALITY) {
230                 struct stat32 statbuf;
231
232                 if (!umove_or_printaddr(tcp, addr, &statbuf))
233                         do_printstat32(tcp, &statbuf);
234                 return;
235         }
236 #endif
237
238 #if defined(SPARC) || defined(SPARC64)
239         if (current_personality == 1) {
240                 struct solstat statbuf;
241
242                 if (!umove_or_printaddr(tcp, addr, &statbuf))
243                         do_printstat_sol(tcp, &statbuf);
244                 return;
245         }
246 #endif /* SPARC || SPARC64 */
247
248         if (!umove_or_printaddr(tcp, addr, &statbuf))
249                 do_printstat(tcp, &statbuf);
250 }
251
252 SYS_FUNC(stat)
253 {
254         if (entering(tcp)) {
255                 printpath(tcp, tcp->u_arg[0]);
256                 tprints(", ");
257         } else {
258                 printstat(tcp, tcp->u_arg[1]);
259         }
260         return 0;
261 }
262
263 SYS_FUNC(fstat)
264 {
265         if (entering(tcp)) {
266                 printfd(tcp, tcp->u_arg[0]);
267                 tprints(", ");
268         } else {
269                 printstat(tcp, tcp->u_arg[1]);
270         }
271         return 0;
272 }
273
274 #if defined STAT32_PERSONALITY && !defined HAVE_STRUCT_STAT64
275 # if defined AARCH64 || defined X86_64 || defined X32
276 /*
277  * Linux x86_64 and x32 have unified `struct stat' but their i386 personality
278  * needs `struct stat64'.
279  * linux/arch/x86/include/uapi/asm/stat.h defines `struct stat64' only for i386.
280  *
281  * Similarly, aarch64 has a unified `struct stat' but its arm personality
282  * needs `struct stat64' (unlike x86, it shouldn't be packed).
283  */
284 struct stat64 {
285         unsigned long long      st_dev;
286         unsigned char   __pad0[4];
287         unsigned int    __st_ino;
288         unsigned int    st_mode;
289         unsigned int    st_nlink;
290         unsigned int    st_uid;
291         unsigned int    st_gid;
292         unsigned long long      st_rdev;
293         unsigned char   __pad3[4];
294         long long       st_size;
295         unsigned int    st_blksize;
296         unsigned long long      st_blocks;
297         unsigned int    st_atime;
298         unsigned int    st_atime_nsec;
299         unsigned int    st_mtime;
300         unsigned int    st_mtime_nsec;
301         unsigned int    st_ctime;
302         unsigned int    st_ctime_nsec;
303         unsigned long long      st_ino;
304 }
305 #  if defined X86_64 || defined X32
306   ATTRIBUTE_PACKED
307 #   define STAT64_SIZE  96
308 #  else
309 #   define STAT64_SIZE  104
310 #  endif
311 ;
312 #  define HAVE_STRUCT_STAT64    1
313 # else /* !(AARCH64 || X86_64 || X32) */
314 #  warning FIXME: check whether struct stat64 definition is needed for this architecture!
315 # endif
316 #endif /* STAT32_PERSONALITY && !HAVE_STRUCT_STAT64 */
317
318 #ifdef HAVE_STRUCT_STAT64
319
320 # define DO_PRINTSTAT do_printstat64
321 # define STRUCT_STAT struct stat64
322 # undef HAVE_STRUCT_STAT_ST_FLAGS
323 # undef HAVE_STRUCT_STAT_ST_FSTYPE
324 # undef HAVE_STRUCT_STAT_ST_GEN
325 # include "printstat.h"
326
327 static void
328 printstat64(struct tcb *tcp, long addr)
329 {
330         struct stat64 statbuf;
331
332 # ifdef STAT64_SIZE
333         (void) sizeof(char[sizeof statbuf == STAT64_SIZE ? 1 : -1]);
334 # endif
335
336 # ifdef STAT32_PERSONALITY
337         if (current_personality != STAT32_PERSONALITY) {
338                 printstat(tcp, addr);
339                 return;
340         }
341 # endif /* STAT32_PERSONALITY */
342
343         if (!umove_or_printaddr(tcp, addr, &statbuf))
344                 do_printstat64(tcp, &statbuf);
345 }
346
347 SYS_FUNC(stat64)
348 {
349         if (entering(tcp)) {
350                 printpath(tcp, tcp->u_arg[0]);
351                 tprints(", ");
352         } else {
353                 printstat64(tcp, tcp->u_arg[1]);
354         }
355         return 0;
356 }
357
358 SYS_FUNC(fstat64)
359 {
360         if (entering(tcp)) {
361                 printfd(tcp, tcp->u_arg[0]);
362                 tprints(", ");
363         } else {
364                 printstat64(tcp, tcp->u_arg[1]);
365         }
366         return 0;
367 }
368
369 #else
370
371 SYS_FUNC(stat64)
372 {
373         return sys_stat(tcp);
374 }
375
376 SYS_FUNC(fstat64)
377 {
378         return sys_fstat(tcp);
379 }
380
381 #endif /* HAVE_STRUCT_STAT64 */
382
383 SYS_FUNC(newfstatat)
384 {
385         if (entering(tcp)) {
386                 print_dirfd(tcp, tcp->u_arg[0]);
387                 printpath(tcp, tcp->u_arg[1]);
388                 tprints(", ");
389         } else {
390 #if defined STAT32_PERSONALITY
391                 if (current_personality == STAT32_PERSONALITY)
392                         printstat64(tcp, tcp->u_arg[2]);
393                 else
394                         printstat(tcp, tcp->u_arg[2]);
395 #elif defined HAVE_STRUCT_STAT64
396                 printstat64(tcp, tcp->u_arg[2]);
397 #else
398                 printstat(tcp, tcp->u_arg[2]);
399 #endif /* STAT32_PERSONALITY || HAVE_STRUCT_STAT64 */
400                 tprints(", ");
401                 printflags(at_flags, tcp->u_arg[3], "AT_???");
402         }
403         return 0;
404 }
405
406 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
407
408 static void
409 convertoldstat(const struct __old_kernel_stat *oldbuf, struct stat *newbuf)
410 {
411         memset(newbuf, 0, sizeof(*newbuf));
412         newbuf->st_dev = oldbuf->st_dev;
413         newbuf->st_ino = oldbuf->st_ino;
414         newbuf->st_mode = oldbuf->st_mode;
415         newbuf->st_nlink = oldbuf->st_nlink;
416         newbuf->st_uid = oldbuf->st_uid;
417         newbuf->st_gid = oldbuf->st_gid;
418         newbuf->st_rdev = oldbuf->st_rdev;
419         newbuf->st_size = oldbuf->st_size;
420         newbuf->st_atime = oldbuf->st_atime;
421         newbuf->st_mtime = oldbuf->st_mtime;
422         newbuf->st_ctime = oldbuf->st_ctime;
423 }
424
425 static void
426 printoldstat(struct tcb *tcp, long addr)
427 {
428         struct __old_kernel_stat statbuf;
429         struct stat newstatbuf;
430
431 # if defined(SPARC) || defined(SPARC64)
432         if (current_personality == 1) {
433                 struct solstat statbuf;
434
435                 if (!umove_or_printaddr(tcp, addr, &statbuf))
436                         do_printstat_sol(tcp, &statbuf);
437                 return;
438         }
439 # endif
440
441         if (!umove_or_printaddr(tcp, addr, &statbuf)) {
442                 convertoldstat(&statbuf, &newstatbuf);
443                 do_printstat(tcp, &newstatbuf);
444         }
445 }
446
447 SYS_FUNC(oldstat)
448 {
449         if (entering(tcp)) {
450                 printpath(tcp, tcp->u_arg[0]);
451                 tprints(", ");
452         } else {
453                 printoldstat(tcp, tcp->u_arg[1]);
454         }
455         return 0;
456 }
457
458 SYS_FUNC(oldfstat)
459 {
460         if (entering(tcp)) {
461                 printfd(tcp, tcp->u_arg[0]);
462                 tprints(", ");
463         } else {
464                 printoldstat(tcp, tcp->u_arg[1]);
465         }
466         return 0;
467 }
468
469 #endif /* HAVE_STRUCT___OLD_KERNEL_STAT */
470
471 #if defined(SPARC) || defined(SPARC64)
472
473 SYS_FUNC(xstat)
474 {
475         if (entering(tcp)) {
476                 tprintf("%ld, ", tcp->u_arg[0]);
477                 printpath(tcp, tcp->u_arg[1]);
478                 tprints(", ");
479         } else {
480                 printstat(tcp, tcp->u_arg[2]);
481         }
482         return 0;
483 }
484
485 SYS_FUNC(fxstat)
486 {
487         if (entering(tcp)) {
488                 tprintf("%ld, ", tcp->u_arg[0]);
489                 printfd(tcp, tcp->u_arg[1]);
490                 tprints(", ");
491         } else {
492                 printstat(tcp, tcp->u_arg[2]);
493         }
494         return 0;
495 }
496
497 #endif /* SPARC || SPARC64 */