• fcntl() fails to pass option flags to fs-ext handler

    From [via djgpp@delorie.com]" @21:1/5 to All on Wed Jun 28 17:04:48 2023
    Copy: gvanem@yahoo.no

    Hi all,

    I was trying to make a non-blocking socket in Watt32 via:

    fcntl(sock, F_SETFL, O_NONBLOCK);

    To my surprise, it did nothing. Replacing fcntl() with fcntlsocket() does set the flag correctly, but that's not a portable solution.

    Looking at the libc code, I see the fsext handler is invoked via:

    int
    fcntl(int fd, int cmd, ...)
    {

    /* ... */

    func = __FSEXT_get_function(fd);
    if (func)
    {
    int rv;
    if (__FSEXT_func_wrapper(func, __FSEXT_fcntl, &rv, fd, cmd))
    return rv;
    }

    /* ... */

    }

    From what I can tell, the flags (in va_list) are never passed through to the fsext handler. Has this ever worked? It seems like a bug to me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [via djgpp@delorie.com]" @21:1/5 to J.W. Jagersma on Wed Jun 28 18:11:10 2023
    Copy: gvanem@yahoo.no

    On 2023-06-28 17:04, J.W. Jagersma wrote:
    Hi all,

    I was trying to make a non-blocking socket in Watt32 via:

    fcntl(sock, F_SETFL, O_NONBLOCK);

    To my surprise, it did nothing. Replacing fcntl() with fcntlsocket() does set
    the flag correctly, but that's not a portable solution.

    Looking at the libc code, I see the fsext handler is invoked via:

    int
    fcntl(int fd, int cmd, ...)
    {

    /* ... */

    func = __FSEXT_get_function(fd);
    if (func)
    {
    int rv;
    if (__FSEXT_func_wrapper(func, __FSEXT_fcntl, &rv, fd, cmd))
    return rv;
    }

    /* ... */

    }

    From what I can tell, the flags (in va_list) are never passed through to the fsext handler. Has this ever worked? It seems like a bug to me.

    I see ioctl() suffers from the same issue (and doesn't even pass cmd).

    If I may propose a patch:

    diff --git a/src/libc/compat/ioctl/ioctl.c b/src/libc/compat/ioctl/ioctl.c index f4382755..182be1a6 100644
    --- a/src/libc/compat/ioctl/ioctl.c
    +++ b/src/libc/compat/ioctl/ioctl.c
    @@ -336,8 +336,17 @@ int ioctl(int fd, int cmd, ...)
    ** see if this is a file system extension file
    **
    */
    - if (func && __FSEXT_func_wrapper(func, __FSEXT_ioctl, &rv, fd))
    - return rv;
    + if (func)
    + {
    + char *arg;
    +
    + va_start(args, cmd);
    + arg = va_arg(args, char *);
    + va_end(args);
    +
    + if (__FSEXT_func_wrapper(func, __FSEXT_ioctl, &rv, fd, cmd, arg))
    + return rv;
    + }

    va_start(args, cmd);

    diff --git a/src/libc/posix/fcntl/fcntl.c b/src/libc/posix/fcntl/fcntl.c
    index e08ffe2b..1d43c0ff 100644
    --- a/src/libc/posix/fcntl/fcntl.c
    +++ b/src/libc/posix/fcntl/fcntl.c
    @@ -281,8 +281,13 @@ fcntl(int fd, int cmd, ...)
    func = __FSEXT_get_function(fd);
    if (func)
    {
    - int rv;
    - if (__FSEXT_func_wrapper(func, __FSEXT_fcntl, &rv, fd, cmd))
    + int rv, arg;
    +
    + va_start(ap, cmd);
    + arg = va_arg(ap, int);
    + va_end(ap);
    +
    + if (__FSEXT_func_wrapper