Шрифт:
Вот тут-то все веселье и начинается. С точки зрения высокого уровня, мы выделяем буфер (он называется reply_msg), в котором собираемся разместить результат операции. Затем мы используем dp, чтобы «прогуляться» по буферу, заполняя его по ходу дела элементами
На первый взгляд этот код может показаться неэффективным; мы используем функцию sprintf для создания двухбайтового имени файла (символ имени файла и признак конца строки NULL) в буфере длиной _POSIX_PATH_MAX (то есть 256) байт. Это делается для того, чтобы сделать код по возможности универсальным.
Наконец, обратите внимание, что мы используем поле offset в OCB для указания, для какого конкретного файла мы в данный момент генерируем структуру
Возврат данных клиенту осуществляется «обычным» способом при помощи функции MsgReply. Заметьте, что поле состояния (status) функции MsgReply используется для указания числа отправленных клиенту байт.
В функции my_read_file мы видим код, почти аналогичный простому примеру функции чтения, который приведен выше в данном разделе. Единственная странная вещь, которую мы здесь делаем — поскольку мы знаем, что возвращается всегда только один байт данных, значит, если параметр nbytes не равен нулю, то он должен быть равен единице (и ничему другому). Таким образом, мы можем создавать данные, подлежащие возврату, непосредственным заполнением символьной переменной string. Обратите внимание, как мы используем поле inode атрибутной записи для определения, какие данные возвращать. Это обычный прием для администраторов, обслуживающих несколько ресурсов. Дополнительным трюком было бы расширить атрибутную запись (мы говорили об этом в разделе «Расширение атрибутной записи») и хранить непосредственно в ней либо сами данные, либо указатель на них.