Hatred's Log Place

DON'T PANIC!

Jul 25, 2019 - 2 minute read - programming

IOCTL: ENOIOCTLCMD vs ENOTTY

Что возвращать из обработчика IOCTL в user-space если данный IOCTL не поддерживается? В нашем драйвере активно использовался ENOIOCTLCMD. Проблема в том, что он объявлен в linux/errno.h в заголовке которого написано (вольный перевод):

не использовать в пользовательском коде

В данном случае, под пользовательским кодом стоит понимать всё, что не собирается в дереве ядра. Кто-то может не согласить со мной в этом аспекте, но по соображениям переносимости - лучше этому следовать.

Кроме того:

  • этого кода нет в пользовательских errno.h/cerrno;
  • для этого когда strerror() вернёт что-то вроде: Unknown error 515 (номер может и отличаться);
  • константы для этого кода ошибки нет на других платформах (Windows, MacOSX, FreeBSD).

Что использовать-то? А использовать не совсем очевидный: ENOTTY.

Изначально, да и согласно комментариям в include/uapi/asm-generic/errno-base.h:

Not a typewriter

При этом утилита пользовательского пространства errno из комплекта moreutils говорит:

ENOTTY 25 Inappropriate ioctl for device

Дополнительными аргументами:

  • интернеты тоже подсказывают такую трактовку;
  • в ядре Linux оно используется по такому же назначению.

В чём же отличие? Нашёл отличное объяснение в block/ioctl.c:

 * Is it an unrecognized ioctl? The correct returns are either
 * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a
 * fallback"). ENOIOCTLCMD gets turned into ENOTTY by the ioctl
 * code before returning.

Не буду переводить, просто поясню: ENOIOCTLCMD используется во внутренних реализациях, когда есть предположение, что обработку можно выполнить в каком-то стандартном русле, выполнить т.н. fallback. В пользовательское пространство должен вернуться ENOTTY. Точка.