gen_ioctls_list.sh
#!/bin/bash
# vim: set sw=4 expandtab:
#
# Licence: GPLv2+
# Copyright (c) 2015-2020, Jérôme Pouiller
#

CC=$1
SYSROOT=$($CC -print-sysroot)
ARCH=$($CC -print-multiarch)
# These subdirectories come from the include/uapi of the linux kernel. If
# ioctls appear outside of these directories, it means either they come from
# staging (and are not stable), or they are architecture dependent or from
# a third-party (valgrind for example).
# Also exclude "drm" directory since it is not exported on most distibutions
SUBDIRS=" linux misc mtd rdma scsi sound video xen asm-generic $ARCH/asm"
INCDIRS="$(for s in $SUBDIRS; do echo " $SYSROOT/usr/include/$s"; done)"

EXCLUDE_FILES+=" --exclude kfd_ioctl.h"         # Need drm/drm.h
EXCLUDE_FILES+=" --exclude kvm.h"               # Too many architecture dependent ioctls
EXCLUDE_FILES+=" --exclude coda.h"              # Include time.h
EXCLUDE_FILES+=" --exclude ioctl.h"             # Does not contain any ioctls
EXCLUDE_IOCTLS+=" -e AUTOFS_IOC_SETTIMEOUT32"   # Lacks type size
EXCLUDE_IOCTLS+=" -e USBDEVFS_CONTROL32"        # Lacks type size
EXCLUDE_IOCTLS+=" -e USBDEVFS_BULK32"           # Lacks type size
EXCLUDE_IOCTLS+=" -e USBDEVFS_SUBMITURB32"      # Lacks type size
EXCLUDE_IOCTLS+=" -e USBDEVFS_DISCSIGNAL32"     # Lacks type size
EXCLUDE_IOCTLS+=" -e USBDEVFS_IOCTL32"          # Lacks type size
EXCLUDE_IOCTLS+=" -e BLKTRACESETUP"             # Lacks type size
EXCLUDE_IOCTLS+=" -e FS_IOC_FIEMAP"             # Lacks type size
EXCLUDE_IOCTLS+=" -e BTRFS_IOC_SET_FSLABEL"     # Lacks type size
EXCLUDE_IOCTLS+=" -e BTRFS_IOC_GET_FSLABEL"     # Lacks type size
EXCLUDE_IOCTLS+=" -e BTRFS_IOC_DEFRAG_RANGE"    # Lacks type size
EXCLUDE_IOCTLS+=" -e XSDFEC_IS_ACTIVE"          # Lacks type size
EXCLUDE_IOCTLS+=" -e XSDFEC_SET_BYPASS"         # Lacks type size
EXCLUDE_IOCTLS+=" -e TIOCGISO7816"              # Lacks type size
EXCLUDE_IOCTLS+=" -e TIOCSISO7816"              # Lacks type size
EXCLUDE_IOCTLS+=" -e RFKILL_IOCTL_MAX_SIZE"     # Parsing error
EXCLUDE_IOCTLS+=" -e COMPAT_ATM_ADDPARTY"       # Parsing error
EXCLUDE_IOCTLS+=" -e MMC_IOC_MULTI_CMD"         # Missing include
EXCLUDE_IOCTLS+=" -e MMC_IOC_CMD"               # Missing include
EXCLUDE_IOCTLS+=" -e BLKELVGET"                 # Inside #if 0
EXCLUDE_IOCTLS+=" -e BLKELVSET"                 # Inside #if 0

# There are multiple problems:
#  - Some declarations do not match regular expression -> Not yet supported
#    (possibility to add them manually to list, but there are problems with
#    foreign platforms)
#  - Sometimes, ioctls disappear and this breaks compilation
#  - Sometimes, headers are renamed or disappear and this breaks compilation

drop_prefix() {
    sed -re "s|$SYSROOT/usr/include/($ARCH/)?||g"
}

get_header_list() {
    grep -lr $EXCLUDE_FILES '^#define[^(].*[ 	]_IO[RW]*(' $INCDIRS
}

show_includes() {
    HEADERS="$1"
    echo "$HEADERS" | drop_prefix | sed -e "s|\(.*\)|#include <\1>|" | sort
}

show_ioctls() {
    HEADERS="$1"
    grep -n '^#define[^(]*[ 	]_IO[RW]*(' $HEADERS |
        drop_prefix |
        grep -v $EXCLUDE_IOCTLS |
        sed -e "s|\(.*\):.*:#define[ 	]*\([A-Z0-9x_]*\).*|    { \"\2\", \2, -1, -1 }, // \1|" |
        sort
}

get_c_file() {
    HEADERS="$1"
    echo '/*'
    echo ' * Licence: GPLv2+'
    echo ' *'
    echo ' * File generated by gen_ioctls_list.sh'
    echo ' * In case of problem, please read README.md'
    echo ' */'
    echo '#include "ioctls_list.h"'
    echo '#include <asm/termbits.h>' # struct termios2
    echo '#include <linux/types.h>'  # other types
    # Place your extra headers here
    echo
    show_includes "$HEADERS"
    echo
    echo "const struct ioctl_entry ioctls_list[] = {"
    show_ioctls "$HEADERS"
    # Place your extra entries here
    echo "    { NULL, 0 },"
    echo "};"
}

get_c_file "$(get_header_list)"
