summaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/journal/sd-journal.c10
-rw-r--r--src/readahead/readahead-collect.c2
-rw-r--r--src/shared/macro.h17
-rw-r--r--src/shared/util.c5
4 files changed, 26 insertions, 8 deletions
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 88777cbcb..e92f20b63 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -1248,11 +1248,11 @@ static void check_network(sd_journal *j, int fd) {
1248 return; 1248 return;
1249 1249
1250 j->on_network = 1250 j->on_network =
1251 (unsigned __SWORD_TYPE) sfs.f_type == CIFS_MAGIC_NUMBER || 1251 CMP_F_TYPE(sfs.f_type, CIFS_MAGIC_NUMBER) ||
1252 (unsigned __SWORD_TYPE) sfs.f_type == CODA_SUPER_MAGIC || 1252 CMP_F_TYPE(sfs.f_type, CODA_SUPER_MAGIC) ||
1253 (unsigned __SWORD_TYPE) sfs.f_type == NCP_SUPER_MAGIC || 1253 CMP_F_TYPE(sfs.f_type, NCP_SUPER_MAGIC) ||
1254 (unsigned __SWORD_TYPE) sfs.f_type == NFS_SUPER_MAGIC || 1254 CMP_F_TYPE(sfs.f_type, NFS_SUPER_MAGIC) ||
1255 (unsigned __SWORD_TYPE) sfs.f_type == SMB_SUPER_MAGIC; 1255 CMP_F_TYPE(sfs.f_type, SMB_SUPER_MAGIC);
1256} 1256}
1257 1257
1258static int add_file(sd_journal *j, const char *prefix, const char *filename) { 1258static int add_file(sd_journal *j, const char *prefix, const char *filename) {
diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
index fbfa8e786..19703aa60 100644
--- a/src/readahead/readahead-collect.c
+++ b/src/readahead/readahead-collect.c
@@ -505,7 +505,7 @@ done:
505 on_ssd = fs_on_ssd(root) > 0; 505 on_ssd = fs_on_ssd(root) > 0;
506 log_debug("On SSD: %s", yes_no(on_ssd)); 506 log_debug("On SSD: %s", yes_no(on_ssd));
507 507
508 on_btrfs = statfs(root, &sfs) >= 0 && (unsigned __SWORD_TYPE) sfs.f_type == BTRFS_SUPER_MAGIC; 508 on_btrfs = statfs(root, &sfs) >= 0 && CMP_F_TYPE(sfs.f_type, BTRFS_SUPER_MAGIC);
509 log_debug("On btrfs: %s", yes_no(on_btrfs)); 509 log_debug("On btrfs: %s", yes_no(on_btrfs));
510 510
511 if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) { 511 if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 9bf81dc3c..f91f7de76 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -264,6 +264,23 @@ do { \
264 } \ 264 } \
265} while(false) 265} while(false)
266 266
267/* Remove this macro, when the kernel has f_type as unsigned int or long
268 * for every architecure. Currently some 64bit architecures (like s390x)
269 * have int in the kernel, but long in userspace for f_type, so glibc
270 * extends the int to long and carries over the sign. Negative numbers are
271 * caused by the 32bit magic constants in linux/magic.h stuffed into the
272 * signed int in the kernel and these negative numbers are extended to
273 * long, which cannot be simply compared to the magic constants anymore.
274 */
275#define CMP_F_TYPE(f, c) \
276 __extension__ ({ \
277 __SWORD_TYPE _f = (f); \
278 const __SWORD_TYPE _c = (c); \
279 const int _c32 = (c); \
280 (_f == _c || _f == _c32 ); \
281 })
282
283
267/* Returns the number of chars needed to format variables of the 284/* Returns the number of chars needed to format variables of the
268 * specified type as a decimal string. Adds in extra space for a 285 * specified type as a decimal string. Adds in extra space for a
269 * negative '-' prefix. */ 286 * negative '-' prefix. */
diff --git a/src/shared/util.c b/src/shared/util.c
index 386973b3f..2a8046922 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2779,8 +2779,9 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
2779 2779
2780static int is_temporary_fs(struct statfs *s) { 2780static int is_temporary_fs(struct statfs *s) {
2781 assert(s); 2781 assert(s);
2782 return (unsigned __SWORD_TYPE) s->f_type == TMPFS_MAGIC || 2782 return
2783 (unsigned __SWORD_TYPE) s->f_type == RAMFS_MAGIC; 2783 CMP_F_TYPE(s->f_type, TMPFS_MAGIC) ||
2784 CMP_F_TYPE(s->f_type, RAMFS_MAGIC);
2784} 2785}
2785 2786
2786int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) { 2787int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {