[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: ioctl-patch for Darwin and FreeBSD
From: |
Bruno Haible |
Subject: |
Re: ioctl-patch for Darwin and FreeBSD |
Date: |
Tue, 22 Feb 2011 23:06:51 +0100 |
User-agent: |
KMail/1.9.9 |
Eric Blake wrote:
> Maybe the real problem is that we need to ensure that our replacement
> does not do sign extension.
Yup, I think that's the point.
> Does this patch fix your issue?
>
> diff --git i/lib/ioctl.c w/lib/ioctl.c
> index 72f9f37..3ed4327 100644
> --- i/lib/ioctl.c
> +++ w/lib/ioctl.c
> @@ -37,7 +37,11 @@ rpl_ioctl (int fd, int request, ... /* {void *,char
> *} arg */)
> buf = va_arg (args, void *);
> va_end (args);
>
> - return ioctl (fd, request, buf);
> + /* Generally, this replacement function is in effect when the system
> + ioctl expects unsigned long int. If request has the most
> + significant bit set, then we need to make sure that
> + sign-extension does not come into play. */
> + return ioctl (fd, (unsigned long) request, buf);
> }
This is a nop, because a cast from 'int' to 'unsigned long' will sign-extend,
not zero-extend.
$ cat foo.c
#include <sys/socket.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <stdio.h>
unsigned long original = SIOCSIFLLADDR;
int as_int = SIOCSIFLLADDR;
unsigned long cast_via_ulong = (unsigned long)(int)SIOCSIFLLADDR;
unsigned long cast_via_uint = (unsigned int)(int)SIOCSIFLLADDR;
int main ()
{
printf ("original = 0x%016lx\n", original);
printf ("as_int = 0x%08x\n", as_int);
printf ("cast_via_ulong = 0x%016lx\n", cast_via_ulong);
printf ("cast_via_uint = 0x%016lx\n", cast_via_uint);
return 0;
}
$ gcc -m64 -Wall foo.c
$ ./a.out
original = 0x000000008020693c
as_int = 0x8020693c
cast_via_ulong = 0xffffffff8020693c
cast_via_uint = 0x000000008020693c
Bruno
--
In memoriam Sophie Scholl <http://en.wikipedia.org/wiki/Sophie_Scholl>