From b90d9b889588ca1cfd5667d1fa703d976edd71ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Mon, 4 Oct 2010 12:53:11 +0200 Subject: work around buggy S_ISxxx(m) implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are buggy implementations of S_ISxxx(m) macros on some platforms (e.g. NetBSD). The issue is that NetBSD doesn't take care to wrap its macro arguments in parentheses, so on Linux and sane systems we have S_ISREG(m) defined as something like: (((m) & S_IFMT) == S_IFREG) But on NetBSD: ((m & _S_IFMT) == _S_IFREG) Since a caller in builtin/diff.c called our macro as `S_IFREG | 0644' this bug introduced a logic error on NetBSD, since the precedence of bit-wise & is higher than | in C. [jc: took change description from Ævar Arnfjörð Bjarmason's patch] Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano diff --git a/cache.h b/cache.h index 2ef2fa3..3d5ed51 100644 --- a/cache.h +++ b/cache.h @@ -277,9 +277,16 @@ static inline int ce_to_dtype(const struct cache_entry *ce) else return DT_UNKNOWN; } -#define canon_mode(mode) \ - (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ - S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK) +static inline unsigned int canon_mode(unsigned int mode) +{ + if (S_ISREG(mode)) + return S_IFREG | ce_permissions(mode); + if (S_ISLNK(mode)) + return S_IFLNK; + if (S_ISDIR(mode)) + return S_IFDIR; + return S_IFGITLINK; +} #define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7) #define cache_entry_size(len) flexible_size(cache_entry,len) -- cgit v0.10.2-6-g49f6