1/* Convert between the kernel's `struct stat' format, and libc's.
2 Copyright (C) 1991-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <sys/stat.h>
21#include <kernel_stat.h>
22
23#ifdef STAT_IS_KERNEL_STAT
24
25/* Dummy. */
26struct kernel_stat;
27
28#else
29
30#include <string.h>
31
32
33#if XSTAT_IS_XSTAT64
34int
35__xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
36{
37 switch (vers)
38 {
39 case _STAT_VER_KERNEL:
40 /* Nothing to do. The struct is in the form the kernel expects.
41 We should have short-circuted before we got here, but for
42 completeness... */
43 *(struct kernel_stat *) ubuf = *kbuf;
44 break;
45
46 case _STAT_VER_LINUX:
47 {
48 struct stat *buf = ubuf;
49
50 /* Convert to current kernel version of `struct stat'. */
51 buf->st_dev = kbuf->st_dev;
52#ifdef _HAVE_STAT___PAD1
53 buf->__pad1 = 0;
54#endif
55 buf->st_ino = kbuf->st_ino;
56 buf->st_mode = kbuf->st_mode;
57 buf->st_nlink = kbuf->st_nlink;
58 buf->st_uid = kbuf->st_uid;
59 buf->st_gid = kbuf->st_gid;
60 buf->st_rdev = kbuf->st_rdev;
61#ifdef _HAVE_STAT___PAD2
62 buf->__pad2 = 0;
63#endif
64 buf->st_size = kbuf->st_size;
65 buf->st_blksize = kbuf->st_blksize;
66 buf->st_blocks = kbuf->st_blocks;
67#ifdef _HAVE_STAT_NSEC
68 buf->st_atim.tv_sec = kbuf->st_atim.tv_sec;
69 buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec;
70 buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec;
71 buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec;
72 buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec;
73 buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec;
74#else
75 buf->st_atime = kbuf->st_atime;
76 buf->st_mtime = kbuf->st_mtime;
77 buf->st_ctime = kbuf->st_ctime;
78#endif
79#ifdef _HAVE_STAT___UNUSED1
80 buf->__glibc_reserved1 = 0;
81#endif
82#ifdef _HAVE_STAT___UNUSED2
83 buf->__glibc_reserved2 = 0;
84#endif
85#ifdef _HAVE_STAT___UNUSED3
86 buf->__glibc_reserved3 = 0;
87#endif
88#ifdef _HAVE_STAT___UNUSED4
89 buf->__glibc_reserved4 = 0;
90#endif
91#ifdef _HAVE_STAT___UNUSED5
92 buf->__glibc_reserved5 = 0;
93#endif
94 }
95 break;
96
97 default:
98 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
99 }
100
101 return 0;
102}
103#endif
104
105int
106__xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
107{
108#if XSTAT_IS_XSTAT64
109 return __xstat_conv (vers, kbuf, ubuf);
110#else
111 switch (vers)
112 {
113 case _STAT_VER_LINUX:
114 {
115 struct stat64 *buf = ubuf;
116
117 /* Convert to current kernel version of `struct stat64'. */
118 buf->st_dev = kbuf->st_dev;
119#ifdef _HAVE_STAT64___PAD1
120 buf->__pad1 = 0;
121#endif
122 buf->st_ino = kbuf->st_ino;
123#ifdef _HAVE_STAT64___ST_INO
124 buf->__st_ino = kbuf->st_ino;
125#endif
126 buf->st_mode = kbuf->st_mode;
127 buf->st_nlink = kbuf->st_nlink;
128 buf->st_uid = kbuf->st_uid;
129 buf->st_gid = kbuf->st_gid;
130 buf->st_rdev = kbuf->st_rdev;
131#ifdef _HAVE_STAT64___PAD2
132 buf->__pad2 = 0;
133#endif
134 buf->st_size = kbuf->st_size;
135 buf->st_blksize = kbuf->st_blksize;
136 buf->st_blocks = kbuf->st_blocks;
137#ifdef _HAVE_STAT64_NSEC
138 buf->st_atim.tv_sec = kbuf->st_atim.tv_sec;
139 buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec;
140 buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec;
141 buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec;
142 buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec;
143 buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec;
144#else
145 buf->st_atime = kbuf->st_atime;
146 buf->st_mtime = kbuf->st_mtime;
147 buf->st_ctime = kbuf->st_ctime;
148#endif
149#ifdef _HAVE_STAT64___UNUSED1
150 buf->__glibc_reserved1 = 0;
151#endif
152#ifdef _HAVE_STAT64___UNUSED2
153 buf->__glibc_reserved2 = 0;
154#endif
155#ifdef _HAVE_STAT64___UNUSED3
156 buf->__glibc_reserved3 = 0;
157#endif
158#ifdef _HAVE_STAT64___UNUSED4
159 buf->__glibc_reserved4 = 0;
160#endif
161#ifdef _HAVE_STAT64___UNUSED5
162 buf->__glibc_reserved5 = 0;
163#endif
164 }
165 break;
166
167 /* If struct stat64 is different from struct stat then
168 _STAT_VER_KERNEL does not make sense. */
169 case _STAT_VER_KERNEL:
170 default:
171 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
172 }
173
174 return 0;
175#endif
176}
177
178int
179__xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
180{
181 switch (vers)
182 {
183 case _STAT_VER_LINUX:
184 {
185 /* Convert current kernel version of `struct stat64' to
186 `struct stat'. */
187 buf->st_dev = kbuf->st_dev;
188#ifdef _HAVE_STAT___PAD1
189 buf->__pad1 = 0;
190#endif
191 buf->st_ino = kbuf->st_ino;
192 if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino)
193 && buf->st_ino != kbuf->st_ino)
194 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
195 buf->st_mode = kbuf->st_mode;
196 buf->st_nlink = kbuf->st_nlink;
197 buf->st_uid = kbuf->st_uid;
198 buf->st_gid = kbuf->st_gid;
199 buf->st_rdev = kbuf->st_rdev;
200#ifdef _HAVE_STAT___PAD2
201 buf->__pad2 = 0;
202#endif
203 buf->st_size = kbuf->st_size;
204 /* Check for overflow. */
205 if (sizeof (buf->st_size) != sizeof (kbuf->st_size)
206 && buf->st_size != kbuf->st_size)
207 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
208 buf->st_blksize = kbuf->st_blksize;
209 buf->st_blocks = kbuf->st_blocks;
210 /* Check for overflow. */
211 if (sizeof (buf->st_blocks) != sizeof (kbuf->st_blocks)
212 && buf->st_blocks != kbuf->st_blocks)
213 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
214#ifdef _HAVE_STAT_NSEC
215 buf->st_atim.tv_sec = kbuf->st_atim.tv_sec;
216 buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec;
217 buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec;
218 buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec;
219 buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec;
220 buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec;
221#else
222 buf->st_atime = kbuf->st_atime;
223 buf->st_mtime = kbuf->st_mtime;
224 buf->st_ctime = kbuf->st_ctime;
225#endif
226
227#ifdef _HAVE_STAT___UNUSED1
228 buf->__glibc_reserved1 = 0;
229#endif
230#ifdef _HAVE_STAT___UNUSED2
231 buf->__glibc_reserved2 = 0;
232#endif
233#ifdef _HAVE_STAT___UNUSED3
234 buf->__glibc_reserved3 = 0;
235#endif
236#ifdef _HAVE_STAT___UNUSED4
237 buf->__glibc_reserved4 = 0;
238#endif
239#ifdef _HAVE_STAT___UNUSED5
240 buf->__glibc_reserved5 = 0;
241#endif
242 }
243 break;
244
245 /* If struct stat64 is different from struct stat then
246 _STAT_VER_KERNEL does not make sense. */
247 case _STAT_VER_KERNEL:
248 default:
249 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
250 }
251
252 return 0;
253}
254
255#endif
256