1 /* Convert between the kernel's `struct stat' format, and libc's.
2 Copyright (C) 1991-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
21 #include <kernel_stat.h>
24 #if !STAT_IS_KERNEL_STAT
31 __xstat_conv (int vers
, struct kernel_stat
*kbuf
, void *ubuf
)
35 case _STAT_VER_KERNEL
:
36 /* Nothing to do. The struct is in the form the kernel expects.
37 We should have short-circuted before we got here, but for
39 *(struct kernel_stat
*) ubuf
= *kbuf
;
44 struct stat
*buf
= ubuf
;
46 /* Convert to current kernel version of `struct stat'. */
47 buf
->st_dev
= kbuf
->st_dev
;
48 #ifdef _HAVE_STAT___PAD1
51 buf
->st_ino
= kbuf
->st_ino
;
52 buf
->st_mode
= kbuf
->st_mode
;
53 buf
->st_nlink
= kbuf
->st_nlink
;
54 buf
->st_uid
= kbuf
->st_uid
;
55 buf
->st_gid
= kbuf
->st_gid
;
56 buf
->st_rdev
= kbuf
->st_rdev
;
57 #ifdef _HAVE_STAT___PAD2
60 buf
->st_size
= kbuf
->st_size
;
61 buf
->st_blksize
= kbuf
->st_blksize
;
62 buf
->st_blocks
= kbuf
->st_blocks
;
63 #ifdef _HAVE_STAT_NSEC
64 buf
->st_atim
.tv_sec
= kbuf
->st_atim
.tv_sec
;
65 buf
->st_atim
.tv_nsec
= kbuf
->st_atim
.tv_nsec
;
66 buf
->st_mtim
.tv_sec
= kbuf
->st_mtim
.tv_sec
;
67 buf
->st_mtim
.tv_nsec
= kbuf
->st_mtim
.tv_nsec
;
68 buf
->st_ctim
.tv_sec
= kbuf
->st_ctim
.tv_sec
;
69 buf
->st_ctim
.tv_nsec
= kbuf
->st_ctim
.tv_nsec
;
71 buf
->st_atime
= kbuf
->st_atime
;
72 buf
->st_mtime
= kbuf
->st_mtime
;
73 buf
->st_ctime
= kbuf
->st_ctime
;
75 #ifdef _HAVE_STAT___UNUSED1
76 buf
->__glibc_reserved1
= 0;
78 #ifdef _HAVE_STAT___UNUSED2
79 buf
->__glibc_reserved2
= 0;
81 #ifdef _HAVE_STAT___UNUSED3
82 buf
->__glibc_reserved3
= 0;
84 #ifdef _HAVE_STAT___UNUSED4
85 buf
->__glibc_reserved4
= 0;
87 #ifdef _HAVE_STAT___UNUSED5
88 buf
->__glibc_reserved5
= 0;
94 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL
);
102 __xstat64_conv (int vers
, struct kernel_stat
*kbuf
, void *ubuf
)
105 return __xstat_conv (vers
, kbuf
, ubuf
);
109 case _STAT_VER_LINUX
:
111 struct stat64
*buf
= ubuf
;
113 /* Convert to current kernel version of `struct stat64'. */
114 buf
->st_dev
= kbuf
->st_dev
;
115 #ifdef _HAVE_STAT64___PAD1
118 buf
->st_ino
= kbuf
->st_ino
;
119 #ifdef _HAVE_STAT64___ST_INO
120 buf
->__st_ino
= kbuf
->st_ino
;
122 buf
->st_mode
= kbuf
->st_mode
;
123 buf
->st_nlink
= kbuf
->st_nlink
;
124 buf
->st_uid
= kbuf
->st_uid
;
125 buf
->st_gid
= kbuf
->st_gid
;
126 buf
->st_rdev
= kbuf
->st_rdev
;
127 #ifdef _HAVE_STAT64___PAD2
130 buf
->st_size
= kbuf
->st_size
;
131 buf
->st_blksize
= kbuf
->st_blksize
;
132 buf
->st_blocks
= kbuf
->st_blocks
;
133 #ifdef _HAVE_STAT64_NSEC
134 buf
->st_atim
.tv_sec
= kbuf
->st_atim
.tv_sec
;
135 buf
->st_atim
.tv_nsec
= kbuf
->st_atim
.tv_nsec
;
136 buf
->st_mtim
.tv_sec
= kbuf
->st_mtim
.tv_sec
;
137 buf
->st_mtim
.tv_nsec
= kbuf
->st_mtim
.tv_nsec
;
138 buf
->st_ctim
.tv_sec
= kbuf
->st_ctim
.tv_sec
;
139 buf
->st_ctim
.tv_nsec
= kbuf
->st_ctim
.tv_nsec
;
141 buf
->st_atime
= kbuf
->st_atime
;
142 buf
->st_mtime
= kbuf
->st_mtime
;
143 buf
->st_ctime
= kbuf
->st_ctime
;
145 #ifdef _HAVE_STAT64___UNUSED1
146 buf
->__glibc_reserved1
= 0;
148 #ifdef _HAVE_STAT64___UNUSED2
149 buf
->__glibc_reserved2
= 0;
151 #ifdef _HAVE_STAT64___UNUSED3
152 buf
->__glibc_reserved3
= 0;
154 #ifdef _HAVE_STAT64___UNUSED4
155 buf
->__glibc_reserved4
= 0;
157 #ifdef _HAVE_STAT64___UNUSED5
158 buf
->__glibc_reserved5
= 0;
163 /* If struct stat64 is different from struct stat then
164 _STAT_VER_KERNEL does not make sense. */
165 case _STAT_VER_KERNEL
:
167 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL
);
175 __xstat32_conv (int vers
, struct stat64
*kbuf
, struct stat
*buf
)
179 case _STAT_VER_LINUX
:
181 /* Convert current kernel version of `struct stat64' to
183 buf
->st_dev
= kbuf
->st_dev
;
184 #ifdef _HAVE_STAT___PAD1
187 buf
->st_ino
= kbuf
->st_ino
;
188 if (sizeof (buf
->st_ino
) != sizeof (kbuf
->st_ino
)
189 && buf
->st_ino
!= kbuf
->st_ino
)
190 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW
);
191 buf
->st_mode
= kbuf
->st_mode
;
192 buf
->st_nlink
= kbuf
->st_nlink
;
193 buf
->st_uid
= kbuf
->st_uid
;
194 buf
->st_gid
= kbuf
->st_gid
;
195 buf
->st_rdev
= kbuf
->st_rdev
;
196 #ifdef _HAVE_STAT___PAD2
199 buf
->st_size
= kbuf
->st_size
;
200 /* Check for overflow. */
201 if (sizeof (buf
->st_size
) != sizeof (kbuf
->st_size
)
202 && buf
->st_size
!= kbuf
->st_size
)
203 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW
);
204 buf
->st_blksize
= kbuf
->st_blksize
;
205 buf
->st_blocks
= kbuf
->st_blocks
;
206 /* Check for overflow. */
207 if (sizeof (buf
->st_blocks
) != sizeof (kbuf
->st_blocks
)
208 && buf
->st_blocks
!= kbuf
->st_blocks
)
209 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW
);
210 #ifdef _HAVE_STAT_NSEC
211 buf
->st_atim
.tv_sec
= kbuf
->st_atim
.tv_sec
;
212 buf
->st_atim
.tv_nsec
= kbuf
->st_atim
.tv_nsec
;
213 buf
->st_mtim
.tv_sec
= kbuf
->st_mtim
.tv_sec
;
214 buf
->st_mtim
.tv_nsec
= kbuf
->st_mtim
.tv_nsec
;
215 buf
->st_ctim
.tv_sec
= kbuf
->st_ctim
.tv_sec
;
216 buf
->st_ctim
.tv_nsec
= kbuf
->st_ctim
.tv_nsec
;
218 buf
->st_atime
= kbuf
->st_atime
;
219 buf
->st_mtime
= kbuf
->st_mtime
;
220 buf
->st_ctime
= kbuf
->st_ctime
;
223 #ifdef _HAVE_STAT___UNUSED1
224 buf
->__glibc_reserved1
= 0;
226 #ifdef _HAVE_STAT___UNUSED2
227 buf
->__glibc_reserved2
= 0;
229 #ifdef _HAVE_STAT___UNUSED3
230 buf
->__glibc_reserved3
= 0;
232 #ifdef _HAVE_STAT___UNUSED4
233 buf
->__glibc_reserved4
= 0;
235 #ifdef _HAVE_STAT___UNUSED5
236 buf
->__glibc_reserved5
= 0;
241 /* If struct stat64 is different from struct stat then
242 _STAT_VER_KERNEL does not make sense. */
243 case _STAT_VER_KERNEL
:
245 return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL
);