]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/uclibc/files/armeb-kernel-stat.h.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / uclibc / files / armeb-kernel-stat.h.patch
1 # The 2.6 asm/stat.h for ARM has some rather unusual transmogrifications
2 # for big-endian running.  This patch adds ARM specific code in xstatconv.c
3 # which deals with the 2.4->2.6 ABI change.
4 --- uClibc-0.9.27/libc/sysdeps/linux/common/xstatconv.c 2005-01-11 23:59:21.000000000 -0800
5 +++ uClibc-0.9.27/libc/sysdeps/linux/common/xstatconv.c 2005-06-05 11:03:56.742587966 -0700
6 @@ -18,7 +18,14 @@
7     02111-1307 USA. 
8     
9     Modified for uClibc by Erik Andersen <andersen@codepoet.org>
10 +   Further modified for ARMBE by John Bowler <jbowler@acm.org>
11     */
12 +/* This is a copy of common/xstatconv.c with a fixup for the ABI
13 + * (structure layout) change in ARM Linux 2.6 - this shifts the
14 + * st_dev and st_rdev information from the start of the 8 byte
15 + * space to the end on big-endian ARM (only).  The code is unchanged
16 + * on little endian.
17 + */
18  
19  #define _GNU_SOURCE
20  #define _LARGEFILE64_SOURCE
21 @@ -32,6 +39,84 @@
22  #include <sys/stat.h>
23  #include "xstatconv.h"
24  
25 +/* Only for ARMEB and LFS. */
26 +#if defined(__ARMEB__) && defined(__UCLIBC_HAS_LFS__)
27 +/* stat64 (renamed) from 2.6.11.11.  What happened here is that after
28 + * Linux 2.4 the 2.4 unsigned short st_rdev and st_dev fields were
29 + * lengthened to unsigned long long - causing the inclusion of at least
30 + * some of the 0 padding bytes which followed them.  On little endian
31 + * this is fine because 2.4 did zero the pad bytes (I think) and the
32 + * position of the data did not change.  On big endian the change
33 + * shifted the data to the end of the field.  Someone noticed for the
34 + * struct stat, and the armeb (big endian) case preserved the
35 + * unsigned short (yuck), but no so for stat64 (maybe this was deliberate,
36 + * but there is no evidence in the code of this.)  Consequently a
37 + * fixup is necessary for the stat64 case.  The fixup here is to
38 + * use the new structure when the change is detected.  See below.
39 + */
40 +struct __kernel_stat64_armeb {
41 +       /* This definition changes the layout on big-endian from that
42 +        * used in 2.4.31 - ABI change!  Likewise for st_rdev.
43 +        */
44 +       unsigned long long      st_dev;
45 +       unsigned char   __pad0[4];
46 +       unsigned long   __st_ino;
47 +       unsigned int    st_mode;
48 +       unsigned int    st_nlink;
49 +       unsigned long   st_uid;
50 +       unsigned long   st_gid;
51 +       unsigned long long      st_rdev;
52 +       unsigned char   __pad3[4];
53 +       long long       st_size;
54 +       unsigned long   st_blksize;
55 +       unsigned long   __pad4;
56 +       unsigned long   st_blocks;
57 +       unsigned long   st_atime;
58 +       unsigned long   st_atime_nsec;
59 +       unsigned long   st_mtime;
60 +       unsigned long   st_mtime_nsec;
61 +       unsigned long   st_ctime;
62 +       unsigned long   st_ctime_nsec;
63 +       unsigned long long      st_ino;
64 +};
65 +
66 +/* This fixup only works so long as the old struct stat64 is no
67 + * smaller than the new one - the caller of xstatconv uses the
68 + * *old* struct, but the kernel writes the new one.  CASSERT
69 + * detects this at compile time.
70 + */
71 +#define CASSERT(c) do switch (0) { case 0:; case (c):; } while (0)
72 +
73 +void __xstat64_conv_new(struct __kernel_stat64_armeb *kbuf, struct stat64 *buf)
74 +{
75 +    CASSERT(sizeof *kbuf <= sizeof (struct kernel_stat64));
76 +
77 +    /* Convert from new kernel version of `struct stat64'.  */
78 +    buf->st_dev = kbuf->st_dev;
79 +    buf->st_ino = kbuf->st_ino;
80 +#ifdef _HAVE_STAT64___ST_INO
81 +    buf->__st_ino = kbuf->__st_ino;
82 +#endif
83 +    buf->st_mode = kbuf->st_mode;
84 +    buf->st_nlink = kbuf->st_nlink;
85 +    buf->st_uid = kbuf->st_uid;
86 +    buf->st_gid = kbuf->st_gid;
87 +    buf->st_rdev = kbuf->st_rdev;
88 +    buf->st_size = kbuf->st_size;
89 +    buf->st_blksize = kbuf->st_blksize;
90 +    buf->st_blocks = kbuf->st_blocks;
91 +    buf->st_atime = kbuf->st_atime;
92 +    buf->st_mtime = kbuf->st_mtime;
93 +    buf->st_ctime = kbuf->st_ctime;
94 +}
95 +#define _MAY_HAVE_NEW_STAT64 1
96 +#else
97 +#define _MAY_HAVE_NEW_STAT64 0
98 +#endif
99 +
100 +/* The following is taken verbatim from xstatconv.c apart from
101 + * the addition of the _MAY_HAVE_NEW_STAT64 code.
102 + */
103  void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf)
104  {
105      /* Convert to current kernel version of `struct stat'.  */
106 @@ -53,6 +138,19 @@
107  #if defined __UCLIBC_HAS_LFS__
108  void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf)
109  {
110 +#   if _MAY_HAVE_NEW_STAT64
111 +       /* This relies on any device (0,0) not being mountable - i.e.
112 +        * it fails on Linux 2.4 if dev(0,0) is a mountable block file
113 +        * system and itself contains it's own device.  That doesn't
114 +        * happen on Linux 2.4 so far as I can see, but even if it
115 +        * does the API only fails (even then) if 2.4 didn't set all
116 +        * of the pad bytes to 0 (and it does set them to zero.)
117 +        */
118 +       if (kbuf->st_dev == 0 && kbuf->st_rdev == 0) {
119 +           __xstat64_conv_new((struct __kernel_stat64_armeb*)kbuf, buf);
120 +           return;
121 +       }
122 +#   endif
123      /* Convert to current kernel version of `struct stat64'.  */
124      buf->st_dev = kbuf->st_dev;
125      buf->st_ino = kbuf->st_ino;