Thread overview
Trouble with ioctl and variadic arguments
Mar 14, 2005
nod
Mar 14, 2005
nod
March 14, 2005
I go nuts. The appended code works in C but not in D.
What am I doing wrong?

The D version fails on the ioctl call with errno
set to 14, or EFAULT, which means that the supplied
out pointer points to invalid memory.

I have tried other ways of allocating memory,
but since the result is the same I only write the
shortest way here, and it should work.
(68 is the sizeof of the real struct fb_fix_screeninfo)

I assume the problem lies in that ioctl takes variadic
parameters. Is there a correct way to deal with this,
or is this a compiler bug?

D version:
-----
import std.c.stdio; // for printf
import std.c.linux.linux; // for open, close
import std.c.stdlib; // for getErrno

extern (C)
{
// from /usr/include/sys/ioctl.h
int ioctl (int fd, ulong request, ...);

// from /usr/include/linux/fb.h
const int FBIOGET_FSCREENINFO = 0x4602;
}

int main(char[][] args)
{
int fbd;
void* f = malloc(68);

if ( (fbd = open("/dev/fb0", O_RDWR)) == -1 )
printf("open() failed. errno == %i\n", getErrno());

if ( ioctl(fbd, FBIOGET_FSCREENINFO, f) != 0 )
printf("ioctl() failed. errno == %i\n", getErrno());

close(fbd);
return 0;
}
-----

C version:
-----
#include <errno.h> // for errno
#include <stdio.h> // for printf
#include <fcntl.h> // for O_RDWR
#include <sys/ioctl.h> // for ioctl
#include <linux/fb.h> // for FBIOGET_SCREENINFO

int main(void)
{
int fbd;
void* f = malloc(68);

if ( (fbd = open("/dev/fb0", O_RDWR)) == -1 )
printf("open() failed. errno == %i\n", errno);

if ( ioctl(fbd, FBIOGET_FSCREENINFO, f) != 0 )
printf("ioctl() failed. errno == %i\n", errno);

close(fbd);
return 0;
}
-----


March 14, 2005
nod wrote:
> I go nuts. The appended code works in C but not in D.
> What am I doing wrong?
> 
> extern (C)
> {
> // from /usr/include/sys/ioctl.h
> int ioctl (int fd, ulong request, ...); 
> 
> // from /usr/include/linux/fb.h
> const int FBIOGET_FSCREENINFO = 0x4602;
> }

Here is what my C header says:

> /* Perform the I/O control operation specified by REQUEST on FD.
>    One argument may follow; its presence and type depend on REQUEST.
>    Return value depends on REQUEST.  Usually -1 indicates error.  */
> extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

Remember that "long" translates to int in D,
it is "long long" that translates to long...

Thus it becomes:
extern(C) int ioctl (int fd, uint request, ...);

Another reason why we need a tool to translate
these headers, instead of having to do it manually ?

--anders
March 14, 2005
In article <d144mn$1m3t$1@digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...
>
>Thus it becomes:
>extern(C) int ioctl (int fd, uint request, ...);

Oww, that's a subtle one... I was actually scratching my head over why the D test program was pushing an extra dword onto the stack. Well it's obvious now isn't it? :)

>
>Another reason why we need a tool to translate
>these headers, instead of having to do it manually ?
>

Indeed. That would make the switch less painful.

Oh, and thanks a million!
//nod