• Re: Fix passing fcntl and ioctl variadic arguments to file system exten

    From [via djgpp@delorie.com]" @21:1/5 to Pali on Sat May 11 13:21:05 2024
    To: dj@delorie.com (DJ Delorie)
    Copy: djgpp@delorie.com

    Date: Thu, 9 May 2024 20:20:19 +0200
    From: Pali <pali@pali.im>
    Cc: djgpp@delorie.com

    Hello. I have there a change which fixes ioctl and fcntl functions when
    file descriptor uses file system extension API. These two functions are
    takes variadic arguments and file system extension API takes va_list structure with all corresponding arguments. djgpp code currently do not
    pass all arguments to API functions __FSEXT_ioctl and __FSEXT_fcntl.

    My fix, which is below, uses __builtin_apply_args() which returns
    pointer to va_list-compatible structure of all arguments (including non-variadic). It works for djgpp i386 calling convention. It does not
    work on e.g. AMD64, but this is not a djgpp case which is 32-bit x86.
    For using __builtin_apply_args, it was required to manually inline __FSEXT_func_wrapper function as it takes variadic arguments and not
    va_list structure as the "func" itself.

    ISTR that the rest of the arguments can be accessed because they are
    on the stack.

    Anyway, I'm not familiar with this code well enough to review these
    patches, but I do know that the code is tricky because ioctl and fcntl
    have "dynamic" signature, and the actual arguments depend on the
    IOCTL/FCNTL function being invoked. I hope someone else (DJ?) could
    review the patches. Sorry.

    And I have there small cleanup, which removes dead code in local static function _unix_ioctl. This function is called only when __FSEXT_ioctl rejected the call and there is no need to call __FSEXT_get_function()
    second time if the first time it returned NULL (no FSEXT).

    maybe I'm misreading the code, but AFAIU it can call _unix_ioctl also
    when FSEXT is non-NULL, but __FSEXT_func_wrapper returned zero. So
    I'm not sure this patch is correct.

    Thanks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [via djgpp@delorie.com]" @21:1/5 to Pali on Sat May 11 14:24:05 2024
    Copy: dj@delorie.com
    Copy: djgpp@delorie.com

    Date: Sat, 11 May 2024 13:06:55 +0200
    From: Pali <pali@pali.im>
    Cc: DJ Delorie <dj@delorie.com>, djgpp@delorie.com

    __FSEXT_Function *func = __FSEXT_get_function(fd);
    if(func)
    {
    int rv;
    if (__FSEXT_func_wrapper(func, __FSEXT_ioctl, &rv, fd))
    return rv;
    }

    What can happen is:

    1) fd is not of fsext type
    - func is NULL and the fsext condition is skipped
    - _unix_ioctl continue

    2) fs is of fsext type and fsext function success
    - func is called and then "return rv" is called
    - _unix_ioctl finish execution

    3) fs is of fsext type but fsext function does not handle _unix_ioctl
    - func is executed but returns false
    - _unix_ioctl continue

    But option 2 cannot happen because during execution of ioctl function
    (before it passed control to _unix_ioctl function) it was already
    checked that fd is either not of fsext type OR fsext does not have
    particular ioctl code.

    So what can happen is either option 1 or 3. Which means that fsext
    cannot handle particular ioctl code and so I think that it does not make sense to call fsext function.

    So if we ever change the calling code to do something that would
    invalidate the conclusion that the two calls to __FSEXT_func_wrapper
    do exactly the same, Someone(TM) will need to remember to go back and
    reinstate the removed call? Is that reasonable?

    But if DJ agrees with you, I won't argue.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)