1 /* Convert between the kernel's `struct stat' format, and libc's.
2    Copyright (C) 1991-2021 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 <assert.h>
20 #include <errno.h>
21 #include <sys/stat.h>
22 #include <kernel_stat.h>
23 #include <string.h>
24 
25 int
__xstat_conv(int vers,struct kernel_stat * kbuf,void * ubuf)26 __xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
27 {
28   switch (vers)
29     {
30     case _STAT_VER_KERNEL:
31       /* Nothing to do.  The struct is in the form the kernel expects.
32          We should have short-circuted before we got here, but for
33          completeness... */
34       *(struct kernel_stat *) ubuf = *kbuf;
35       break;
36 
37     case _STAT_VER_LINUX:
38       {
39 	struct stat *buf = ubuf;
40 
41 	/* Convert to current kernel version of `struct stat'.  */
42 	buf->st_dev = kbuf->st_dev;
43 	buf->__pad1 = 0;
44 	buf->st_ino = kbuf->st_ino;
45 	buf->st_mode = kbuf->st_mode;
46 	buf->st_nlink = kbuf->st_nlink;
47 	buf->st_uid = kbuf->st_uid;
48 	buf->st_gid = kbuf->st_gid;
49 	buf->st_rdev = kbuf->st_rdev;
50 	buf->__pad2 = 0;
51 	buf->st_size = kbuf->st_size;
52 	buf->st_blksize = kbuf->st_blksize;
53 	buf->st_blocks = kbuf->st_blocks;
54 	buf->st_atim.tv_sec = kbuf->st_atime_sec;
55 	buf->st_atim.tv_nsec = 0;
56 	buf->st_mtim.tv_sec = kbuf->st_mtime_sec;
57 	buf->st_mtim.tv_nsec = 0;
58 	buf->st_ctim.tv_sec = kbuf->st_ctime_sec;
59 	buf->st_ctim.tv_nsec = 0;
60 	buf->__glibc_reserved4 = 0;
61 	buf->__glibc_reserved5 = 0;
62       }
63       break;
64 
65     default:
66       __set_errno (EINVAL);
67       return -1;
68     }
69 
70   return 0;
71 }
72 
73 int
__xstat32_conv(int vers,struct stat64 * sbuf,struct stat * buf)74 __xstat32_conv (int vers, struct stat64 *sbuf, struct stat *buf)
75 {
76   struct kernel_stat64 *kbuf;
77 
78   /* *stat64 syscalls on sparc64 really fill in struct kernel_stat64,
79      rather than struct stat64.  But it is the same size as
80      struct kernel_stat64, so use this hack so that we can reuse
81      i386 {,f,l}xstat{,at}.c routines.  */
82   __asm ("" : "=r" (kbuf) : "0" (sbuf));
83   assert (sizeof (struct stat) == sizeof (struct stat64));
84   assert (sizeof (struct stat64) >= sizeof (struct kernel_stat64));
85 
86   switch (vers)
87     {
88     case _STAT_VER_LINUX:
89       {
90 	/* Convert current kernel version of `struct stat64' to
91            `struct stat'.  */
92 	buf->st_dev = kbuf->st_dev;
93 	buf->__pad1 = 0;
94 	buf->st_ino = kbuf->st_ino;
95 	buf->st_mode = kbuf->st_mode;
96 	buf->st_nlink = kbuf->st_nlink;
97 	buf->st_uid = kbuf->st_uid;
98 	buf->st_gid = kbuf->st_gid;
99 	buf->st_rdev = kbuf->st_rdev;
100 	buf->__pad2 = 0;
101 	buf->st_size = kbuf->st_size;
102 	buf->st_blksize = kbuf->st_blksize;
103 	buf->st_blocks = kbuf->st_blocks;
104 	buf->st_atim.tv_sec = kbuf->st_atime_sec;
105 	buf->st_atim.tv_nsec = kbuf->st_atime_nsec;
106 	buf->st_mtim.tv_sec = kbuf->st_mtime_sec;
107 	buf->st_mtim.tv_nsec = kbuf->st_mtime_nsec;
108 	buf->st_ctim.tv_sec = kbuf->st_ctime_sec;
109 	buf->st_ctim.tv_nsec = kbuf->st_ctime_nsec;
110 	buf->__glibc_reserved4 = 0;
111 	buf->__glibc_reserved5 = 0;
112       }
113       break;
114 
115       /* If struct stat64 is different from struct stat then
116 	 _STAT_VER_KERNEL does not make sense.  */
117     case _STAT_VER_KERNEL:
118     default:
119       __set_errno (EINVAL);
120       return -1;
121     }
122 
123   return 0;
124 }
125