summaryrefslogtreecommitdiff
path: root/ioctl.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-03-20 10:57:41 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2012-03-20 10:57:41 +0100
commit1c2e912cc3e1be4081334b9ce0114c10a72166c6 (patch)
tree81737a579dd1385fdb24464935e605b50abd5e97 /ioctl.c
parent8cf2c261eada67a137c7d118edf305f010e469ff (diff)
downloadstrace-1c2e912cc3e1be4081334b9ce0114c10a72166c6.tar.gz
strace-1c2e912cc3e1be4081334b9ce0114c10a72166c6.tar.bz2
strace-1c2e912cc3e1be4081334b9ce0114c10a72166c6.tar.xz
Simplify search in ioctl table
text data bss dec hex filename 236973 704 18944 256621 3ea6d strace.before 236929 704 18944 256577 3ea41 strace * ioctl.c (compare): Simplify generation of compare result. (ioctl_lookup): Pass key directly, not as part of dummy struct. (ioctl_next_match): More readable code. No logic changes. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'ioctl.c')
-rw-r--r--ioctl.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/ioctl.c b/ioctl.c
index 630a335..b638093 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -29,30 +29,50 @@
*/
#include "defs.h"
+#include <limits.h>
#include <asm/ioctl.h>
static int
compare(const void *a, const void *b)
{
- unsigned long code1 = ((struct ioctlent *) a)->code;
+ unsigned long code1 = (long) a;
unsigned long code2 = ((struct ioctlent *) b)->code;
- return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0;
+
+ /* Simply returning (code1 - code2) may be wrong.
+ * Exmaple: 0xffffffff - 0 = 0xffffffff = -1.
+ * Need to shift both values down until they both fit
+ * in positive int.
+ */
+ while ((code1|code2) > INT_MAX) {
+#if INT_MAX == LONG_MAX
+ /* this case is easy */
+ code1 >>= 1;
+ code2 >>= 1;
+ break;
+#else
+ /* Remove INT_MAX worth of bits, then check again */
+ code1 >>= sizeof(int) * 8 - 1;
+ code2 >>= sizeof(int) * 8 - 1;
+#endif
+ }
+ return (int)code1 - (int)code2;
}
const struct ioctlent *
ioctl_lookup(long code)
{
- struct ioctlent *iop, ioent;
+ struct ioctlent *iop;
- ioent.code = code;
- ioent.code &= (_IOC_NRMASK<<_IOC_NRSHIFT) | (_IOC_TYPEMASK<<_IOC_TYPESHIFT);
- iop = (struct ioctlent *) bsearch((char *) &ioent, (char *) ioctlent,
- nioctlents, sizeof(struct ioctlent), compare);
- while (iop > ioctlent)
- if ((--iop)->code != ioent.code) {
+ code &= (_IOC_NRMASK<<_IOC_NRSHIFT) | (_IOC_TYPEMASK<<_IOC_TYPESHIFT);
+ iop = bsearch((void*)code, ioctlent,
+ nioctlents, sizeof(ioctlent[0]), compare);
+ while (iop > ioctlent) {
+ iop--;
+ if (iop->code != code) {
iop++;
break;
}
+ }
return iop;
}
@@ -61,7 +81,8 @@ ioctl_next_match(const struct ioctlent *iop)
{
long code;
- code = (iop++)->code;
+ code = iop->code;
+ iop++;
if (iop < ioctlent + nioctlents && iop->code == code)
return iop;
return NULL;