]> granicus.if.org Git - strace/blob - file.c
Use <asm/unistd.h> instead of <sys/syscall.h>
[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 # include "stat32.h"
101 #endif
102
103 #ifdef STAT32_PERSONALITY
104 # define DO_PRINTSTAT do_printstat32
105 # define STRUCT_STAT struct stat32
106 # undef HAVE_STRUCT_STAT_ST_FLAGS
107 # undef HAVE_STRUCT_STAT_ST_FSTYPE
108 # undef HAVE_STRUCT_STAT_ST_GEN
109 # include "printstat.h"
110 #endif /* STAT32_PERSONALITY */
111
112 static void
113 printstat(struct tcb *tcp, long addr)
114 {
115         struct stat statbuf;
116
117 #ifdef STAT32_PERSONALITY
118         if (current_personality == STAT32_PERSONALITY) {
119                 struct stat32 statbuf;
120
121                 if (!umove_or_printaddr(tcp, addr, &statbuf))
122                         do_printstat32(tcp, &statbuf);
123                 return;
124         }
125 #endif
126
127         if (!umove_or_printaddr(tcp, addr, &statbuf))
128                 do_printstat(tcp, &statbuf);
129 }
130
131 SYS_FUNC(stat)
132 {
133         if (entering(tcp)) {
134                 printpath(tcp, tcp->u_arg[0]);
135                 tprints(", ");
136         } else {
137                 printstat(tcp, tcp->u_arg[1]);
138         }
139         return 0;
140 }
141
142 SYS_FUNC(fstat)
143 {
144         if (entering(tcp)) {
145                 printfd(tcp, tcp->u_arg[0]);
146                 tprints(", ");
147         } else {
148                 printstat(tcp, tcp->u_arg[1]);
149         }
150         return 0;
151 }
152
153 #if defined STAT32_PERSONALITY && !defined HAVE_STRUCT_STAT64
154 # if defined AARCH64 || defined X86_64 || defined X32
155 /*
156  * Linux x86_64 and x32 have unified `struct stat' but their i386 personality
157  * needs `struct stat64'.
158  * linux/arch/x86/include/uapi/asm/stat.h defines `struct stat64' only for i386.
159  *
160  * Similarly, aarch64 has a unified `struct stat' but its arm personality
161  * needs `struct stat64' (unlike x86, it shouldn't be packed).
162  */
163 struct stat64 {
164         unsigned long long      st_dev;
165         unsigned char   __pad0[4];
166         unsigned int    __st_ino;
167         unsigned int    st_mode;
168         unsigned int    st_nlink;
169         unsigned int    st_uid;
170         unsigned int    st_gid;
171         unsigned long long      st_rdev;
172         unsigned char   __pad3[4];
173         long long       st_size;
174         unsigned int    st_blksize;
175         unsigned long long      st_blocks;
176         unsigned int    st_atime;
177         unsigned int    st_atime_nsec;
178         unsigned int    st_mtime;
179         unsigned int    st_mtime_nsec;
180         unsigned int    st_ctime;
181         unsigned int    st_ctime_nsec;
182         unsigned long long      st_ino;
183 }
184 #  if defined X86_64 || defined X32
185   ATTRIBUTE_PACKED
186 #   define STAT64_SIZE  96
187 #  else
188 #   define STAT64_SIZE  104
189 #  endif
190 ;
191 #  define HAVE_STRUCT_STAT64    1
192 # else /* !(AARCH64 || X86_64 || X32) */
193 #  warning FIXME: check whether struct stat64 definition is needed for this architecture!
194 # endif
195 #endif /* STAT32_PERSONALITY && !HAVE_STRUCT_STAT64 */
196
197 #ifdef HAVE_STRUCT_STAT64
198
199 # define DO_PRINTSTAT do_printstat64
200 # define STRUCT_STAT struct stat64
201 # undef HAVE_STRUCT_STAT_ST_FLAGS
202 # undef HAVE_STRUCT_STAT_ST_FSTYPE
203 # undef HAVE_STRUCT_STAT_ST_GEN
204 # include "printstat.h"
205
206 static void
207 printstat64(struct tcb *tcp, long addr)
208 {
209         struct stat64 statbuf;
210
211 # ifdef STAT64_SIZE
212         (void) sizeof(char[sizeof statbuf == STAT64_SIZE ? 1 : -1]);
213 # endif
214
215 # ifdef STAT32_PERSONALITY
216         if (current_personality != STAT32_PERSONALITY) {
217                 printstat(tcp, addr);
218                 return;
219         }
220 # endif /* STAT32_PERSONALITY */
221
222         if (!umove_or_printaddr(tcp, addr, &statbuf))
223                 do_printstat64(tcp, &statbuf);
224 }
225
226 SYS_FUNC(stat64)
227 {
228         if (entering(tcp)) {
229                 printpath(tcp, tcp->u_arg[0]);
230                 tprints(", ");
231         } else {
232                 printstat64(tcp, tcp->u_arg[1]);
233         }
234         return 0;
235 }
236
237 SYS_FUNC(fstat64)
238 {
239         if (entering(tcp)) {
240                 printfd(tcp, tcp->u_arg[0]);
241                 tprints(", ");
242         } else {
243                 printstat64(tcp, tcp->u_arg[1]);
244         }
245         return 0;
246 }
247
248 #else
249
250 SYS_FUNC(stat64)
251 {
252         return sys_stat(tcp);
253 }
254
255 SYS_FUNC(fstat64)
256 {
257         return sys_fstat(tcp);
258 }
259
260 #endif /* HAVE_STRUCT_STAT64 */
261
262 SYS_FUNC(newfstatat)
263 {
264         if (entering(tcp)) {
265                 print_dirfd(tcp, tcp->u_arg[0]);
266                 printpath(tcp, tcp->u_arg[1]);
267                 tprints(", ");
268         } else {
269 #if defined STAT32_PERSONALITY
270                 if (current_personality == STAT32_PERSONALITY)
271                         printstat64(tcp, tcp->u_arg[2]);
272                 else
273                         printstat(tcp, tcp->u_arg[2]);
274 #elif defined HAVE_STRUCT_STAT64
275                 printstat64(tcp, tcp->u_arg[2]);
276 #else
277                 printstat(tcp, tcp->u_arg[2]);
278 #endif /* STAT32_PERSONALITY || HAVE_STRUCT_STAT64 */
279                 tprints(", ");
280                 printflags(at_flags, tcp->u_arg[3], "AT_???");
281         }
282         return 0;
283 }
284
285 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
286
287 static void
288 convertoldstat(const struct __old_kernel_stat *oldbuf, struct stat *newbuf)
289 {
290         memset(newbuf, 0, sizeof(*newbuf));
291         newbuf->st_dev = oldbuf->st_dev;
292         newbuf->st_ino = oldbuf->st_ino;
293         newbuf->st_mode = oldbuf->st_mode;
294         newbuf->st_nlink = oldbuf->st_nlink;
295         newbuf->st_uid = oldbuf->st_uid;
296         newbuf->st_gid = oldbuf->st_gid;
297         newbuf->st_rdev = oldbuf->st_rdev;
298         newbuf->st_size = oldbuf->st_size;
299         newbuf->st_atime = oldbuf->st_atime;
300         newbuf->st_mtime = oldbuf->st_mtime;
301         newbuf->st_ctime = oldbuf->st_ctime;
302 }
303
304 static void
305 printoldstat(struct tcb *tcp, long addr)
306 {
307         struct __old_kernel_stat statbuf;
308         struct stat newstatbuf;
309
310         if (!umove_or_printaddr(tcp, addr, &statbuf)) {
311                 convertoldstat(&statbuf, &newstatbuf);
312                 do_printstat(tcp, &newstatbuf);
313         }
314 }
315
316 SYS_FUNC(oldstat)
317 {
318         if (entering(tcp)) {
319                 printpath(tcp, tcp->u_arg[0]);
320                 tprints(", ");
321         } else {
322                 printoldstat(tcp, tcp->u_arg[1]);
323         }
324         return 0;
325 }
326
327 SYS_FUNC(oldfstat)
328 {
329         if (entering(tcp)) {
330                 printfd(tcp, tcp->u_arg[0]);
331                 tprints(", ");
332         } else {
333                 printoldstat(tcp, tcp->u_arg[1]);
334         }
335         return 0;
336 }
337
338 #endif /* HAVE_STRUCT___OLD_KERNEL_STAT */
339
340 #if defined(SPARC) || defined(SPARC64)
341
342 SYS_FUNC(xstat)
343 {
344         if (entering(tcp)) {
345                 tprintf("%ld, ", tcp->u_arg[0]);
346                 printpath(tcp, tcp->u_arg[1]);
347                 tprints(", ");
348         } else {
349                 printstat(tcp, tcp->u_arg[2]);
350         }
351         return 0;
352 }
353
354 SYS_FUNC(fxstat)
355 {
356         if (entering(tcp)) {
357                 tprintf("%ld, ", tcp->u_arg[0]);
358                 printfd(tcp, tcp->u_arg[1]);
359                 tprints(", ");
360         } else {
361                 printstat(tcp, tcp->u_arg[2]);
362         }
363         return 0;
364 }
365
366 #endif /* SPARC || SPARC64 */