summaryrefslogtreecommitdiff
path: root/src/shared/macro.h
diff options
context:
space:
mode:
authorHarald Hoyer <harald@redhat.com>2013-04-18 07:34:25 +0200
committerHarald Hoyer <harald@redhat.com>2013-04-18 07:34:25 +0200
commitfc6e6d245ee3989c222a2a8cc82a33475f9922f3 (patch)
tree1bac92dfa3d1575e136586f4c549d2ac312cca6c /src/shared/macro.h
parent5521d6985648669a65d0529bb01c7a32edc99294 (diff)
Add ugly CMP_F_TYPE() macro
On some architectures (like s390x) the kernel has the type int for f_type, but long in userspace. Assigning the 32 bit magic constants from linux/magic.h to the 31 bit signed f_type in the kernel, causes f_type to be negative for some constants. glibc extends the int to long for those architecures in 64 bit mode, so the negative int becomes a negative long, which cannot be simply compared to the original magic constant, because the compiler would automatically cast the constant to long. To workaround this issue, we also compare to the (int)MAGIC value in a macro. Of course, we could do #ifdef with the architecure, but it has to be maintained, and the magic constants are 32 bit anyway. Someday, when the int is unsigned or long for all architectures, we can remove this macro again. Until then, keep it as simple as it can be.
Diffstat (limited to 'src/shared/macro.h')
-rw-r--r--src/shared/macro.h17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 9bf81dc3cc..f91f7de769 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -264,6 +264,23 @@ do { \
} \
} while(false)
+/* Remove this macro, when the kernel has f_type as unsigned int or long
+ * for every architecure. Currently some 64bit architecures (like s390x)
+ * have int in the kernel, but long in userspace for f_type, so glibc
+ * extends the int to long and carries over the sign. Negative numbers are
+ * caused by the 32bit magic constants in linux/magic.h stuffed into the
+ * signed int in the kernel and these negative numbers are extended to
+ * long, which cannot be simply compared to the magic constants anymore.
+ */
+#define CMP_F_TYPE(f, c) \
+ __extension__ ({ \
+ __SWORD_TYPE _f = (f); \
+ const __SWORD_TYPE _c = (c); \
+ const int _c32 = (c); \
+ (_f == _c || _f == _c32 ); \
+ })
+
+
/* Returns the number of chars needed to format variables of the
* specified type as a decimal string. Adds in extra space for a
* negative '-' prefix. */